backupper 0.2.2 → 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/README.md +6 -6
- data/backupper.gemspec +2 -2
- data/lib/backupper.rb +0 -1
- data/lib/backupper/backupper.rb +63 -73
- data/lib/backupper/dump_command.rb +20 -0
- data/lib/backupper/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 433774005bc1b3d59b575acf5878d1bb9f202d5f
|
4
|
+
data.tar.gz: 7efb646234fa7392394ce2980728961b13ae196c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f97d4c32a27d19ab7925b6b868acda6325954cfa4870e3a795efd0a96c32930d2ee2258baa95df4fc0ee50aa5a88b9ab4d4d58ad2c9b36e44ed1137c456dbea
|
7
|
+
data.tar.gz: 3439ec0927796ac074a51b51f68d32787c0992622e9dc9c46f38066f55f497bf59a1a15c257d910f5d1411465ecbd84814a530f6f71869cbbd17d6c5965ccaf3
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Backupper
|
2
2
|
|
3
|
-
Backupper is a
|
3
|
+
Backupper is a tool to backup all your databases spread in the world!
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -12,7 +12,7 @@ Backupper is a useful tool to backup all your databases spreaded in the world!
|
|
12
12
|
|
13
13
|
## Configuration file
|
14
14
|
|
15
|
-
A common config file for backupper looks like this:
|
15
|
+
A common [YAML](http://yaml.org/) config file for backupper looks like this:
|
16
16
|
|
17
17
|
```yaml
|
18
18
|
mailer:
|
@@ -36,7 +36,7 @@ db1:
|
|
36
36
|
|
37
37
|
db2:
|
38
38
|
disabled: false
|
39
|
-
dump: '/home/backup/db2
|
39
|
+
dump: '/home/backup/db2'
|
40
40
|
extra_copy: '/mnt/backup-disk/backups/db2'
|
41
41
|
username: user
|
42
42
|
host: '1.2.3.4'
|
@@ -48,7 +48,7 @@ db2:
|
|
48
48
|
db_password: db_Pa$$w0rD
|
49
49
|
```
|
50
50
|
|
51
|
-
After
|
51
|
+
After done all backups a report email is sent to you using gmail smtp service (remember to permit less secure app [here](https://myaccount.google.com/lesssecureapps)).
|
52
52
|
|
53
53
|
⚠️ __WARNING__: the backupper configuration file contains many important passwords, so be careful to lock it and protect it with care!
|
54
54
|
|
@@ -62,9 +62,9 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
62
62
|
|
63
63
|
## About Uqido
|
64
64
|
|
65
|
-
[![uqido](https://
|
65
|
+
[![uqido](https://i.imgur.com/FAo2W7w.png)](http://uqido.com)
|
66
66
|
|
67
67
|
Backupper is maintained and funded by [Uqido](https://uqido.com).
|
68
68
|
The names and logos for Uqido are trademarks of Uqido s.r.l.
|
69
69
|
|
70
|
-
The [Uqido team](https://www.uqido.com
|
70
|
+
The [Uqido team](https://www.uqido.com/en/about-us/).
|
data/backupper.gemspec
CHANGED
@@ -7,10 +7,10 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = 'backupper'
|
8
8
|
spec.version = Backupper::VERSION
|
9
9
|
spec.authors = ['pioz']
|
10
|
-
spec.email = ['
|
10
|
+
spec.email = ['enrico.pilotto@uqido.com']
|
11
11
|
|
12
12
|
spec.summary = %q{Tool to backup databases}
|
13
|
-
spec.description = %q{
|
13
|
+
spec.description = %q{Backupper is a tool to backup all your databases spread in the world}
|
14
14
|
spec.homepage = 'https://github.com/uqido/backupper'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
data/lib/backupper.rb
CHANGED
data/lib/backupper/backupper.rb
CHANGED
@@ -2,6 +2,8 @@ require 'yaml'
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'sshkit'
|
4
4
|
require 'sshkit/dsl'
|
5
|
+
require 'backupper/dump_command'
|
6
|
+
require 'backupper/mailer'
|
5
7
|
include SSHKit::DSL
|
6
8
|
|
7
9
|
class Backupper
|
@@ -23,103 +25,91 @@ class Backupper
|
|
23
25
|
|
24
26
|
def backup!
|
25
27
|
@conf.each do |k, options|
|
26
|
-
o = @default.merge(options)
|
27
28
|
puts "⬇️ backing up #{k}..."
|
28
|
-
|
29
|
-
|
30
|
-
err = 'Invalid directory where to save database dump'
|
31
|
-
error(k, err)
|
32
|
-
puts err
|
33
|
-
next
|
34
|
-
end
|
35
|
-
host = o['host']
|
36
|
-
host = "#{o['username']}@#{host}" if o['username']
|
37
|
-
host = "#{host}:#{o['port']}" if o['port']
|
38
|
-
adapter = o['adapter'] || 'mysql'
|
39
|
-
unless self.respond_to?("#{adapter}_dump_command")
|
40
|
-
err = "Cannot handle adapter '#{adapter}'"
|
41
|
-
error(k, err)
|
42
|
-
puts err
|
43
|
-
next
|
44
|
-
end
|
45
|
-
unless o['database']
|
46
|
-
err = 'Please specify database name!'
|
29
|
+
o, err = setup_options(options)
|
30
|
+
if err
|
47
31
|
error(k, err)
|
48
32
|
puts err
|
49
33
|
next
|
50
34
|
end
|
51
35
|
begin
|
52
36
|
download_dump(
|
53
|
-
key:
|
54
|
-
adapter:
|
55
|
-
|
56
|
-
password:
|
57
|
-
database:
|
58
|
-
db_username:
|
59
|
-
db_password:
|
37
|
+
key: k,
|
38
|
+
adapter: o['adapter'],
|
39
|
+
url: o['url'],
|
40
|
+
password: o['password'],
|
41
|
+
database: o['database'],
|
42
|
+
db_username: o['db_username'],
|
43
|
+
db_password: o['db_password'],
|
60
44
|
dump_options: o['dump_options'],
|
61
|
-
outdir:
|
62
|
-
extra_copy:
|
45
|
+
outdir: o['outdir'],
|
46
|
+
extra_copy: o['extra_copy']
|
63
47
|
)
|
64
48
|
rescue SSHKit::Runner::ExecuteError => e
|
65
49
|
error(k, e.to_s)
|
66
50
|
puts e
|
67
51
|
end
|
68
52
|
end
|
69
|
-
|
70
|
-
begin
|
71
|
-
Mailer.send(from: @mailer['from'], to: @mailer['to'], password: @mailer['password'], report: @report)
|
72
|
-
rescue Net::SMTPAuthenticationError => e
|
73
|
-
puts e
|
74
|
-
end
|
75
|
-
end
|
53
|
+
send_report_email!
|
76
54
|
end
|
77
55
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
56
|
+
def download_dump(key:, adapter: 'mysql', url:, password: nil, database:, db_username: 'root', db_password: nil, dump_options: nil, outdir:, extra_copy: nil)
|
57
|
+
t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
58
|
+
path = nil
|
59
|
+
filename = "#{key}__#{database}.sql.bz2"
|
60
|
+
tempfile = File.join('/tmp', filename)
|
61
|
+
dumpname = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}__#{filename}"
|
62
|
+
path = File.join(outdir, dumpname)
|
63
|
+
on(url) do |client|
|
64
|
+
client.password = password
|
65
|
+
execute 'set -o pipefail; ' + DumpCommand.send(adapter, database: database, username: db_username, password: db_password, dump_options: dump_options, outfile: tempfile)
|
66
|
+
download! tempfile, path
|
67
|
+
execute :rm, tempfile
|
68
|
+
end
|
69
|
+
extra_copy = check_dir(extra_copy)
|
70
|
+
FileUtils.cp(path, extra_copy) if extra_copy
|
71
|
+
@report[key] = {
|
72
|
+
path: File.absolute_path(path),
|
73
|
+
size: (File.size(path).to_f / 2**20).round(2),
|
74
|
+
time: (Process.clock_gettime(Process::CLOCK_MONOTONIC) - t).round(2)
|
75
|
+
}
|
76
|
+
@report[key].merge!({extra_copy: File.absolute_path(File.join(extra_copy, dumpname))}) if extra_copy
|
85
77
|
end
|
86
78
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
79
|
+
private
|
80
|
+
|
81
|
+
def setup_options(options)
|
82
|
+
o = @default.merge(options)
|
83
|
+
o['outdir'] = check_dir(o['dump'].to_s)
|
84
|
+
unless o['outdir']
|
85
|
+
return nil, 'Invalid directory where to save database dump'
|
86
|
+
end
|
87
|
+
unless o['database']
|
88
|
+
return nil, 'Please specify the database name!'
|
89
|
+
end
|
90
|
+
unless o['host']
|
91
|
+
return nil, 'Please specify the host!'
|
92
|
+
end
|
93
|
+
o['url'] = o['host']
|
94
|
+
o['url'] = "#{o['username']}@#{o['url']}" if o['username']
|
95
|
+
o['url'] = "#{o['url']}:#{o['port']}" if o['port']
|
96
|
+
o['adapter'] ||= 'mysql'
|
97
|
+
unless DumpCommand.respond_to?(o['adapter'])
|
98
|
+
return nil, "Cannot handle adapter '#{o['adapter']}'"
|
99
|
+
end
|
100
|
+
return o, nil
|
93
101
|
end
|
94
102
|
|
95
|
-
def
|
96
|
-
if
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
dumpname = "#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}__#{filename}"
|
102
|
-
path = File.join(outdir, dumpname)
|
103
|
-
backupper = self
|
104
|
-
on(host) do |client|
|
105
|
-
client.password = password
|
106
|
-
execute 'set -o pipefail; ' + backupper.send("#{adapter}_dump_command", database: database, username: db_username, password: db_password, dump_options: dump_options, outfile: tempfile)
|
107
|
-
download! tempfile, path
|
108
|
-
execute :rm, tempfile
|
103
|
+
def send_report_email!
|
104
|
+
if @report.any? && @mailer['from'] && @mailer['to'] && @mailer['password']
|
105
|
+
begin
|
106
|
+
Mailer.send(from: @mailer['from'], to: @mailer['to'], password: @mailer['password'], report: @report)
|
107
|
+
rescue Net::SMTPAuthenticationError => e
|
108
|
+
puts e
|
109
109
|
end
|
110
|
-
extra_copy = check_dir(extra_copy)
|
111
|
-
FileUtils.cp(path, extra_copy) if extra_copy
|
112
|
-
@report[key] = {
|
113
|
-
path: File.absolute_path(path),
|
114
|
-
size: (File.size(path).to_f / 2**20).round(2),
|
115
|
-
time: (Time.now - t).round(2)
|
116
|
-
}
|
117
|
-
@report[key].merge!({extra_copy: File.absolute_path(File.join(extra_copy, dumpname))}) if extra_copy
|
118
110
|
end
|
119
111
|
end
|
120
112
|
|
121
|
-
private
|
122
|
-
|
123
113
|
def error(key, error)
|
124
114
|
@report[key] = {error: error}
|
125
115
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DumpCommand
|
2
|
+
|
3
|
+
def self.mysql(database:, username: 'root', password: nil, dump_options: nil, outfile:)
|
4
|
+
params = []
|
5
|
+
params << "--databases '#{database}'"
|
6
|
+
params << "-u#{username}"
|
7
|
+
params << "-p#{password}" if password
|
8
|
+
params << dump_options if dump_options
|
9
|
+
return "mysqldump #{params.join(' ')} | bzip2 > '#{outfile}'"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.postgresql(database:, username: 'root', password: nil, dump_options: nil, outfile:)
|
13
|
+
params = []
|
14
|
+
params << "-U #{username}"
|
15
|
+
params << "'#{database}'"
|
16
|
+
params << dump_options if dump_options
|
17
|
+
return "PGPASSWORD=#{password} pg_dump #{params.join(' ')} | bzip2 > '#{outfile}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/backupper/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backupper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pioz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sshkit
|
@@ -66,9 +66,9 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '10.0'
|
69
|
-
description:
|
69
|
+
description: Backupper is a tool to backup all your databases spread in the world
|
70
70
|
email:
|
71
|
-
-
|
71
|
+
- enrico.pilotto@uqido.com
|
72
72
|
executables:
|
73
73
|
- backupper
|
74
74
|
extensions: []
|
@@ -83,6 +83,7 @@ files:
|
|
83
83
|
- bin/backupper
|
84
84
|
- lib/backupper.rb
|
85
85
|
- lib/backupper/backupper.rb
|
86
|
+
- lib/backupper/dump_command.rb
|
86
87
|
- lib/backupper/mailer.rb
|
87
88
|
- lib/backupper/version.rb
|
88
89
|
homepage: https://github.com/uqido/backupper
|