simple_backup 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +2 -1
- data/backup_example.rb +23 -13
- data/lib/simple_backup/backend/abstract.rb +35 -0
- data/lib/simple_backup/backend/local.rb +45 -0
- data/lib/simple_backup/backends.rb +60 -0
- data/lib/simple_backup/dsl.rb +26 -93
- data/lib/simple_backup/engine.rb +41 -3
- data/lib/simple_backup/source/abstract.rb +130 -0
- data/lib/simple_backup/source/dir.rb +39 -0
- data/lib/simple_backup/source/dir_strategy/bare.rb +17 -0
- data/lib/simple_backup/source/dir_strategy/capistrano.rb +41 -0
- data/lib/simple_backup/source/file.rb +20 -0
- data/lib/simple_backup/source/mysql.rb +28 -0
- data/lib/simple_backup/sources.rb +74 -0
- data/lib/simple_backup/utils/disk_usage.rb +53 -0
- data/lib/simple_backup/utils/logger.rb +92 -0
- data/lib/simple_backup/utils/mailer.rb +126 -0
- data/lib/simple_backup/utils/mysql.rb +65 -0
- data/lib/simple_backup/utils.rb +4 -53
- data/lib/simple_backup/version.rb +2 -2
- data/lib/simple_backup.rb +40 -5
- metadata +17 -19
- data/lib/simple_backup/engine/abstract.rb +0 -42
- data/lib/simple_backup/engine/app_strategy/abstract.rb +0 -13
- data/lib/simple_backup/engine/app_strategy/bare.rb +0 -29
- data/lib/simple_backup/engine/app_strategy/capistrano.rb +0 -44
- data/lib/simple_backup/engine/app_strategy/factory.rb +0 -20
- data/lib/simple_backup/engine/apps.rb +0 -63
- data/lib/simple_backup/engine/mysql.rb +0 -104
- data/lib/simple_backup/exception/app_already_defined.rb +0 -6
- data/lib/simple_backup/exception/apps_dir_does_not_exists.rb +0 -6
- data/lib/simple_backup/exception/base.rb +0 -6
- data/lib/simple_backup/exception/cant_create_dir.rb +0 -6
- data/lib/simple_backup/exception/type_does_not_exists.rb +0 -6
- data/lib/simple_backup/exception.rb +0 -5
- data/lib/simple_backup/logger.rb +0 -84
- data/lib/simple_backup/mailer.rb +0 -138
- data/lib/simple_backup/storage.rb +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db18d1aeca0f0b1e397e8599de6ed70474fd49e1
|
4
|
+
data.tar.gz: 9e70279a4648074f77da59a0f070a869ce8c555d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d94e122a1bfab65a376e29087564568917c939149cec9d52c37d5905dd683687b033b1132fb28bcf6cf373da9f0fc3cb6492fd8cc30fe1c09bb2d38ef3412421
|
7
|
+
data.tar.gz: 00bb1b44ad48000765a9aa84817cc451772886beb03dc41e07a7503cbcf3d2e4d1293844de049caa6987d5d11a0221f57534453cafa9904ff4356d38eae1c54b
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,8 @@ development and its API should be treat as unstable.
|
|
9
9
|
## TODO
|
10
10
|
|
11
11
|
- [ ] Refactorization
|
12
|
-
- [ ] Few
|
12
|
+
- [ ] Few backends for backup store (file, s3, ftp)
|
13
|
+
- [ ] Filters mechanism (e.g. PGP encryption)
|
13
14
|
- [ ] Tests
|
14
15
|
- [ ] Docummentation and examples
|
15
16
|
|
data/backup_example.rb
CHANGED
@@ -1,31 +1,41 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
3
6
|
require 'simple_backup'
|
4
7
|
|
5
8
|
SimpleBackup.run do
|
6
|
-
|
7
|
-
|
9
|
+
log_level :debug
|
10
|
+
|
8
11
|
high_usage_treshold 0.9
|
9
12
|
check_disk_path '/'
|
10
13
|
check_disk_path '/backup'
|
11
14
|
check_disk_path '/home/app'
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
default_keep_last 9
|
17
|
+
|
18
|
+
sources do
|
19
|
+
dir 'app-1', '/home/app/app-1', type: :capistrano, backends: 'backup'
|
20
|
+
dir 'app-2', '/home/app/app-2', backends: :none
|
21
|
+
dir 'none', '/none'
|
22
|
+
|
23
|
+
file 'hosts', '/etc/hosts'
|
15
24
|
|
16
|
-
|
17
|
-
|
25
|
+
mysql 'test1', 'test1'
|
26
|
+
mysql 'test2', 'test2'
|
27
|
+
mysql 'test3', 'test3', exclude_tables: ['t_test1']
|
18
28
|
end
|
19
29
|
|
20
|
-
|
21
|
-
|
30
|
+
backends do
|
31
|
+
local 'backup', path: '/srv/backup'
|
32
|
+
end
|
22
33
|
|
34
|
+
mysql do
|
23
35
|
host 'localhost'
|
24
36
|
port 3306
|
25
|
-
user '
|
26
|
-
pass '
|
27
|
-
db 'test1'
|
28
|
-
db 'test2', exclude_tables: ['t_test1']
|
37
|
+
user 'root'
|
38
|
+
pass 'root'
|
29
39
|
end
|
30
40
|
|
31
41
|
mailer do
|
@@ -33,7 +43,7 @@ SimpleBackup.run do
|
|
33
43
|
|
34
44
|
from 'backup@localhost'
|
35
45
|
to 'root@localhost'
|
36
|
-
cc '
|
46
|
+
cc 'rb@localhost'
|
37
47
|
bcc 'root@localhost'
|
38
48
|
end
|
39
49
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SimpleBackup
|
2
|
+
module Backend
|
3
|
+
class Abstract
|
4
|
+
@@logger = Utils::Logger.instance
|
5
|
+
|
6
|
+
def configure(*args)
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def name=(value)
|
11
|
+
@name = value.gsub(/[^a-zA-Z0-9\-\_\. ]*/, '').gsub(/\s+/, '_').downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
@name
|
16
|
+
end
|
17
|
+
|
18
|
+
def type
|
19
|
+
self.class.name.split('::').last.gsub(/[^a-zA-Z0-9\-\_\. ]*/, '').gsub(/\s+/, '_').downcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def desc
|
23
|
+
'%5s :: %s' % [type, @name]
|
24
|
+
end
|
25
|
+
|
26
|
+
def store(source)
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def cleanup(source)
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SimpleBackup
|
2
|
+
module Backend
|
3
|
+
class Local < Abstract
|
4
|
+
def configure(options = {})
|
5
|
+
raise "Must provide :path option" unless options[:path]
|
6
|
+
|
7
|
+
@path = options[:path]
|
8
|
+
|
9
|
+
raise "#{@path} does not exists" unless ::File.exist?(@path)
|
10
|
+
raise "#{@path} is not a directory" unless ::File.directory?(@path)
|
11
|
+
raise "#{@path} is not writable" unless ::File.writable?(@path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def store(source)
|
15
|
+
storage_path = get_storage_path(source)
|
16
|
+
FileUtils.cp source.backup_file, storage_path
|
17
|
+
end
|
18
|
+
|
19
|
+
def cleanup(source)
|
20
|
+
storage_path = get_storage_path(source)
|
21
|
+
|
22
|
+
files = ::Dir.glob(::File.join(storage_path, '*.tar.gz')).sort
|
23
|
+
|
24
|
+
to_persist = files
|
25
|
+
to_persist = files.slice(source.keep_last * -1, source.keep_last) if files.length > source.keep_last
|
26
|
+
to_remove = files - to_persist
|
27
|
+
|
28
|
+
@@logger.scope_start
|
29
|
+
to_remove.each do |file|
|
30
|
+
FileUtils.rm(file)
|
31
|
+
@@logger.debug "Old backup '#{file}' for source '#{source.desc.strip}' cleaned up from '#{desc.strip}'"
|
32
|
+
end
|
33
|
+
@@logger.scope_end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def get_storage_path(source)
|
38
|
+
path = ::File.join(@path, source.type, source.name)
|
39
|
+
FileUtils.mkpath path unless ::File.exist?(path)
|
40
|
+
|
41
|
+
path
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'simple_backup/backend/abstract'
|
3
|
+
|
4
|
+
module SimpleBackup
|
5
|
+
class Backends
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
@@logger = Utils::Logger.instance
|
9
|
+
@@sources = Sources.instance
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@backends = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def each(&block)
|
16
|
+
@backends.each(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def save_and_cleanup
|
20
|
+
each do |name, backend|
|
21
|
+
@@sources.each do |name, source|
|
22
|
+
next unless source.backup_file and source.supports(backend)
|
23
|
+
|
24
|
+
backend.store(source)
|
25
|
+
@@logger.info "Source '#{source.desc.strip}' stored in backend '#{backend.desc.strip}'"
|
26
|
+
|
27
|
+
backend.cleanup(source)
|
28
|
+
@@logger.info "Source '#{source.desc.strip}' cleaned up in backend '#{backend.desc.strip}'"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(method, *args)
|
34
|
+
backend = create_backend(method)
|
35
|
+
|
36
|
+
return nil if backend.nil?
|
37
|
+
|
38
|
+
name = args.shift
|
39
|
+
options = args.shift
|
40
|
+
options ||= {}
|
41
|
+
|
42
|
+
raise "Name '#{name}' for backend already used" if @backends.has_key?(name.to_sym)
|
43
|
+
|
44
|
+
backend.name = name
|
45
|
+
backend.configure(options)
|
46
|
+
|
47
|
+
@@logger.info "Created backend for: #{backend.desc}"
|
48
|
+
@backends[name.to_sym] = backend
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def create_backend(name)
|
53
|
+
file = "simple_backup/backend/#{name}"
|
54
|
+
|
55
|
+
require file
|
56
|
+
backend_name = Object.const_get("SimpleBackup::Backend::#{name.capitalize}")
|
57
|
+
backend_name.new
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/simple_backup/dsl.rb
CHANGED
@@ -1,120 +1,53 @@
|
|
1
1
|
module SimpleBackup
|
2
|
-
TIMESTAMP = Time.new.strftime('%Y%m%d%H%M%S')
|
3
|
-
@@status = :failed
|
4
|
-
|
5
|
-
def self.status
|
6
|
-
@@status
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.run(&block)
|
10
|
-
Logger::info "Backup #{TIMESTAMP} started"
|
11
|
-
|
12
|
-
dsl = DSL.new
|
13
|
-
|
14
|
-
Logger::scope_start :info, "Configuration"
|
15
|
-
dsl.instance_eval(&block)
|
16
|
-
dsl.prepare
|
17
|
-
Logger::scope_end
|
18
|
-
|
19
|
-
dsl.run
|
20
|
-
dsl.cleanup
|
21
|
-
@@status = :succeed
|
22
|
-
|
23
|
-
Logger::info "Backup #{TIMESTAMP} finished"
|
24
|
-
rescue StandardError => e
|
25
|
-
self.handle_exception(e)
|
26
|
-
ensure
|
27
|
-
dsl.notify
|
28
|
-
Logger::info "Notifications for backup #{TIMESTAMP} finished"
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.handle_exception(e)
|
32
|
-
Logger::error "#{e.class} => #{e.message}"
|
33
|
-
Logger::error "Backup #{TIMESTAMP} failed"
|
34
|
-
STDERR.puts "Error @ #{Time.new.strftime('%Y-%m-%dT%H:%M:%S')}"
|
35
|
-
STDERR.puts "#{e.inspect}"
|
36
|
-
STDERR.puts e.backtrace
|
37
|
-
end
|
38
|
-
|
39
2
|
class DSL
|
40
|
-
|
41
|
-
@storage = Storage.new
|
42
|
-
end
|
43
|
-
|
44
|
-
def prepare
|
45
|
-
if @apps_block
|
46
|
-
@apps = Engine::Apps.new
|
47
|
-
@apps.storage = @storage
|
48
|
-
@apps.instance_eval(&@apps_block)
|
49
|
-
end
|
50
|
-
|
51
|
-
if @mysql_block
|
52
|
-
@mysql = Engine::MySQL.new
|
53
|
-
@mysql.storage = @storage
|
54
|
-
@mysql.instance_eval(&@mysql_block)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def run
|
59
|
-
usage = Utils::Disk::usage
|
60
|
-
Logger::error "Disk high usage treshold exceeded #{usage[:high_usage]}" if usage[:high_usage_exceeded]
|
3
|
+
@@logger = Utils::Logger.instance
|
61
4
|
|
62
|
-
|
63
|
-
@
|
64
|
-
@mysql.backup if @mysql
|
65
|
-
Logger::scope_end
|
5
|
+
def initialize(engine)
|
6
|
+
@engine = engine
|
66
7
|
end
|
67
8
|
|
68
|
-
def
|
69
|
-
|
70
|
-
@apps.cleanup if @apps
|
71
|
-
@mysql.cleanup if @mysql
|
72
|
-
Logger::scope_end
|
73
|
-
end
|
74
|
-
|
75
|
-
def notify
|
76
|
-
@mailer.send if @mailer
|
77
|
-
rescue StandardError => e
|
78
|
-
SimpleBackup.handle_exception(e)
|
9
|
+
def log_level(level)
|
10
|
+
@@logger.level = level
|
79
11
|
end
|
80
12
|
|
81
|
-
def
|
82
|
-
|
83
|
-
sources[:apps] = @apps.sources if @apps
|
84
|
-
sources[:mysql] = @mysql.sources if @mysql
|
13
|
+
def high_usage_treshold(value)
|
14
|
+
@@logger.info "Setting high_usage_treshold to #{value}"
|
85
15
|
|
86
|
-
|
16
|
+
Utils::Disk.high_usage_treshold = value
|
87
17
|
end
|
88
18
|
|
89
|
-
def
|
90
|
-
|
91
|
-
end
|
19
|
+
def check_disk_path(path)
|
20
|
+
@@logger.info "Adding disk path '#{path}' to usage check"
|
92
21
|
|
93
|
-
|
94
|
-
@storage.dir = dir
|
22
|
+
Utils::Disk.add_path(path)
|
95
23
|
end
|
96
24
|
|
97
|
-
def
|
98
|
-
|
99
|
-
Utils::Disk.high_usage_treshold = value
|
25
|
+
def default_keep_last(value)
|
26
|
+
Sources.instance.default_keep_last = value
|
100
27
|
end
|
101
28
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
29
|
+
def sources(&block)
|
30
|
+
sources = Sources.instance
|
31
|
+
sources.instance_eval(&block)
|
105
32
|
end
|
106
33
|
|
107
|
-
def
|
108
|
-
|
34
|
+
def backends(&block)
|
35
|
+
backends = Backends.instance
|
36
|
+
backends.instance_eval(&block)
|
109
37
|
end
|
110
38
|
|
111
39
|
def mysql(&block)
|
112
|
-
|
40
|
+
@@logger.info "Configuring MySQL Util"
|
41
|
+
|
42
|
+
Utils::MySQL.instance.instance_eval(&block)
|
113
43
|
end
|
114
44
|
|
115
45
|
def mailer(&block)
|
116
|
-
|
46
|
+
@@logger.info "Configuring Mailer Util"
|
47
|
+
|
48
|
+
@mailer = Utils::Mailer.new
|
117
49
|
@mailer.instance_eval(&block)
|
50
|
+
@engine.mailer = @mailer
|
118
51
|
end
|
119
52
|
end
|
120
53
|
end
|
data/lib/simple_backup/engine.rb
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module SimpleBackup
|
2
|
+
module Engine
|
3
|
+
class Engine
|
4
|
+
|
5
|
+
@@backends = Backends.instance
|
6
|
+
@@sources = Sources.instance
|
7
|
+
@@logger = Utils::Logger.instance
|
8
|
+
@@mysql = Utils::MySQL.instance
|
9
|
+
|
10
|
+
def mailer=(mailer)
|
11
|
+
@mailer = mailer
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
usage = Utils::Disk::usage
|
16
|
+
|
17
|
+
@@logger.error "Disk high usage treshold exceeded #{usage[:high_usage]}" if usage[:high_usage_exceeded]
|
18
|
+
@@logger.scope_start :info, "Backup"
|
19
|
+
|
20
|
+
@@sources.backup
|
21
|
+
@@backends.save_and_cleanup
|
22
|
+
@@sources.cleanup
|
23
|
+
|
24
|
+
@@logger.scope_end
|
25
|
+
ensure
|
26
|
+
@@mysql.close
|
27
|
+
end
|
28
|
+
|
29
|
+
def notify
|
30
|
+
return unless @mailer
|
31
|
+
@@logger.scope_start :info, "Sending e-mail notification"
|
32
|
+
|
33
|
+
@mailer.send
|
34
|
+
|
35
|
+
@@logger.scope_end :info, "Notifications for backup #{TIMESTAMP} finished"
|
36
|
+
rescue StandardError => e
|
37
|
+
SimpleBackup.handle_exception(e)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'rubygems/package'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
module SimpleBackup
|
6
|
+
module Source
|
7
|
+
class Abstract
|
8
|
+
@@logger = Utils::Logger.instance
|
9
|
+
|
10
|
+
def configure(*args)
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
def keep_last=(value)
|
15
|
+
@keep_last = value
|
16
|
+
end
|
17
|
+
|
18
|
+
def keep_last
|
19
|
+
@keep_last
|
20
|
+
end
|
21
|
+
|
22
|
+
def name=(value)
|
23
|
+
@name = value.gsub(/[^a-zA-Z0-9\-\_\. ]*/, '').gsub(/\s+/, '_').downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def name
|
27
|
+
@name
|
28
|
+
end
|
29
|
+
|
30
|
+
def type
|
31
|
+
self.class.name.split('::').last.gsub(/[^a-zA-Z0-9\-\_\. ]*/, '').gsub(/\s+/, '_').downcase
|
32
|
+
end
|
33
|
+
|
34
|
+
def desc
|
35
|
+
'%5s :: %s' % [type, @name]
|
36
|
+
end
|
37
|
+
|
38
|
+
def get
|
39
|
+
return @backup_file if @backup_file
|
40
|
+
|
41
|
+
@@logger.scope_start :info, "Getting archive for: #{desc}"
|
42
|
+
|
43
|
+
@tmp_dir = ::Dir.mktmpdir('simple_backup-')
|
44
|
+
@@logger.debug "Created tmp directory #{@tmp_dir}"
|
45
|
+
|
46
|
+
data_exists = prepare_data
|
47
|
+
|
48
|
+
@@logger.warning "No data for: #{desc}" unless data_exists
|
49
|
+
archive_data if data_exists
|
50
|
+
|
51
|
+
FileUtils.rm_rf(@tmp_dir)
|
52
|
+
@@logger.debug "Removed tmp directory #{@tmp_dir}"
|
53
|
+
|
54
|
+
@backup_file
|
55
|
+
ensure
|
56
|
+
@@logger.scope_end
|
57
|
+
end
|
58
|
+
|
59
|
+
def cleanup
|
60
|
+
return nil unless @backup_file
|
61
|
+
|
62
|
+
FileUtils.rm (@backup_file)
|
63
|
+
@@logger.debug "Temporary backup file #{@backup_file} was removed"
|
64
|
+
end
|
65
|
+
|
66
|
+
def backup_file
|
67
|
+
@backup_file
|
68
|
+
end
|
69
|
+
|
70
|
+
def backends=(value)
|
71
|
+
@backends = []
|
72
|
+
@backends = @backends + value if value.kind_of?(Array)
|
73
|
+
@backends << value unless value.kind_of?(Array)
|
74
|
+
end
|
75
|
+
|
76
|
+
def supports(backend)
|
77
|
+
return TRUE unless @backends
|
78
|
+
return FALSE unless @backends.include?(backend.name)
|
79
|
+
|
80
|
+
TRUE
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def prepare_data
|
85
|
+
raise NotImplementedError
|
86
|
+
end
|
87
|
+
|
88
|
+
def archive_data
|
89
|
+
filename = "#{type}-#{name}.#{SimpleBackup::TIMESTAMP}.tar.gz"
|
90
|
+
@backup_file = ::File.join(::Dir.tmpdir, filename)
|
91
|
+
|
92
|
+
::File.open(backup_file, 'w') do |f|
|
93
|
+
f.write targz.string
|
94
|
+
end
|
95
|
+
|
96
|
+
@@logger.debug "Backup saved to temporary file #{backup_file}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def targz
|
100
|
+
path = @tmp_dir
|
101
|
+
|
102
|
+
content = StringIO.new('');
|
103
|
+
Gem::Package::TarWriter.new(content) do |tar|
|
104
|
+
::Dir[::File.join(path, '**/*')].each do |file|
|
105
|
+
mode = ::File.stat(file).mode
|
106
|
+
relative_file = file.sub(/^#{Regexp::escape path}\/?/, '')
|
107
|
+
|
108
|
+
if ::File.directory?(file)
|
109
|
+
tar.mkdir(relative_file, mode)
|
110
|
+
else
|
111
|
+
tar.add_file relative_file, mode do |tf|
|
112
|
+
::File.open(file, 'rb') do |f|
|
113
|
+
tf.write f.read
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
content.rewind
|
120
|
+
|
121
|
+
gz = StringIO.new('')
|
122
|
+
zip = Zlib::GzipWriter.new(gz)
|
123
|
+
zip.write content.string
|
124
|
+
zip.close
|
125
|
+
|
126
|
+
gz
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module SimpleBackup
|
2
|
+
module Source
|
3
|
+
class Dir < Abstract
|
4
|
+
def initialize
|
5
|
+
@strategy = :bare
|
6
|
+
end
|
7
|
+
|
8
|
+
def configure(path, options = {})
|
9
|
+
@path = path
|
10
|
+
|
11
|
+
raise "#{path} is a file - use File source instead of Dir" unless !::File.exist?(path) or ::File.directory?(path)
|
12
|
+
@strategy = options[:strategy] if options[:strategy]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def prepare_data
|
17
|
+
return false unless ::File.exist?(@path)
|
18
|
+
|
19
|
+
path_entries = get_path_entries
|
20
|
+
FileUtils.cp_r path_entries, @tmp_dir if path_entries
|
21
|
+
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_path_entries
|
26
|
+
file = "simple_backup/source/dir_strategy/#{@strategy.to_s}"
|
27
|
+
|
28
|
+
require file
|
29
|
+
strategy_name = Object.const_get("SimpleBackup::Source::DirStrategy::#{@strategy.to_s.capitalize}")
|
30
|
+
strategy = strategy_name.new
|
31
|
+
|
32
|
+
strategy.get_entries(@path)
|
33
|
+
rescue Errno::ENOENT
|
34
|
+
@@logger.warning "Path '#{@path}' does not exists"
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SimpleBackup
|
2
|
+
module Source
|
3
|
+
module DirStrategy
|
4
|
+
class Capistrano
|
5
|
+
@@logger = Utils::Logger.instance
|
6
|
+
|
7
|
+
def get_entries(path)
|
8
|
+
shared = shared_path(path)
|
9
|
+
current = current_path(path)
|
10
|
+
paths = [current, shared].compact
|
11
|
+
|
12
|
+
if paths.empty?
|
13
|
+
@@logger.warning "No capistrano paths for application"
|
14
|
+
return nil
|
15
|
+
end
|
16
|
+
|
17
|
+
paths
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def current_path(path)
|
22
|
+
current = ::Dir.new(::File.join(path, 'current') + '/')
|
23
|
+
@@logger.debug "Capistrano current path: #{current.path}"
|
24
|
+
current.path
|
25
|
+
rescue Errno::ENOENT
|
26
|
+
@@logger.warning "No capistrano current path for application"
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def shared_path(path)
|
31
|
+
shared = ::Dir.new(::File.join(path, 'shared'))
|
32
|
+
@@logger.debug "Capistrano shared path: #{shared.path}"
|
33
|
+
shared.path
|
34
|
+
rescue Errno::ENOENT
|
35
|
+
@@logger.warning "No capistrano shared path for application"
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SimpleBackup
|
2
|
+
module Source
|
3
|
+
class File < Abstract
|
4
|
+
def configure(path, options = {})
|
5
|
+
@path = path
|
6
|
+
|
7
|
+
raise "#{path} is a directory - use Dir source instead of File" unless !::File.exist?(path) or ::File.file?(path)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def prepare_data
|
12
|
+
return false unless ::File.exist?(@path)
|
13
|
+
|
14
|
+
FileUtils.cp @path, @tmp_dir
|
15
|
+
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|