backup 4.0.2 → 4.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0598ab928bc914fc5be6f4e473a2dba3f3b80c41
4
- data.tar.gz: d8c34be3b2896bb9a1cc024c67df93783ae1853c
3
+ metadata.gz: b7e83c99df63edb4998a75a49d81a06b0d1039ca
4
+ data.tar.gz: 5080aa4b34f9fc9104a1f312ad7418398b041148
5
5
  SHA512:
6
- metadata.gz: eed55c0c9b7e63ba902db61e8148413a430d21755175c34926ae5348318aefde89876a5dd8231dccef11adaad44ec08575f3e244e7b3ab235e2100e764b9b079
7
- data.tar.gz: 20d0efa09f22cf70b9bdaf94ac49d43f1fbe0d499b44bfe31ac93c0b867559c3db83c87a70953d5def9cfe53caff2308f36dc40cc0b1406cf284d310749c80b2
6
+ metadata.gz: 2e80a87dbf0a0d93cdb5ce0fb9a3f10c9b68b7d2ab2d49b5f30e8a77e3bf5763669ee7f0b853800283f3097c3c18fe0fc53f186dd0fbdb2bb5bacaf58b423c61
7
+ data.tar.gz: 2dacfb012d43a5e19434427d76ddd0ddb3b03913eba7dce02ce3947397be1b7b3f663fb74bcd04e93ee5006c27c7487c2c5cdb61cff1e2200562e5e0bbe0a413
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  Backup v4.x
2
2
  ===========
3
+ [![Code Climate](https://codeclimate.com/github/meskyanichi/backup.png)](https://codeclimate.com/github/meskyanichi/backup)
4
+ [![Build Status](https://travis-ci.org/meskyanichi/backup.svg?branch=master)](https://travis-ci.org/meskyanichi/backup)
3
5
 
4
6
  Backup is a system utility for Linux and Mac OS X, distributed as a RubyGem, that allows you to easily perform backup
5
7
  operations. It provides an elegant DSL in Ruby for _modeling_ your backups. Backup has built-in support for various
@@ -108,6 +108,8 @@ module Backup
108
108
  autoload :Slack, File.join(NOTIFIER_PATH, 'slack')
109
109
  autoload :HttpPost, File.join(NOTIFIER_PATH, 'http_post')
110
110
  autoload :Nagios, File.join(NOTIFIER_PATH, 'nagios')
111
+ autoload :FlowDock, File.join(NOTIFIER_PATH, 'flowdock')
112
+ autoload :Zabbix, File.join(NOTIFIER_PATH, 'zabbix')
111
113
  end
112
114
 
113
115
  ##
@@ -42,7 +42,8 @@ module Backup
42
42
  ],
43
43
  # Notifiers
44
44
  ['Mail', 'Twitter', 'Campfire', 'Prowl',
45
- 'Hipchat', 'Pushover', 'HttpPost', 'Nagios', 'Slack']
45
+ 'Hipchat', 'Pushover', 'HttpPost', 'Nagios',
46
+ 'Slack', 'FlowDock', 'Zabbix']
46
47
  ]
47
48
  )
48
49
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require 'shellwords'
2
3
 
3
4
  module Backup
4
5
  module Database
@@ -32,28 +33,48 @@ module Backup
32
33
  attr_accessor :only_tables
33
34
 
34
35
  ##
35
- # Additional "mysqldump" options
36
+ # Additional "mysqldump" or "innobackupex (backup creation)" options
36
37
  attr_accessor :additional_options
37
38
 
39
+ ##
40
+ # Additional innobackupex log preparation phase ("apply-logs") options
41
+ attr_accessor :prepare_options
42
+
43
+ ##
44
+ # Default is :mysqldump (which is built in MySQL and generates
45
+ # a textual SQL file), but can be changed to :innobackupex, which
46
+ # has more feasible restore times for large databases.
47
+ # See: http://www.percona.com/doc/percona-xtrabackup/
48
+ attr_accessor :backup_engine
49
+
50
+ ##
51
+ # If set the backup engine command block is executed as the given user
52
+ attr_accessor :sudo_user
53
+
54
+ ##
55
+ # If set, do not suppress innobackupdb output (useful for debugging)
56
+ attr_accessor :verbose
57
+
38
58
  def initialize(model, database_id = nil, &block)
39
59
  super
40
60
  instance_eval(&block) if block_given?
41
61
 
42
62
  @name ||= :all
63
+ @backup_engine ||= :mysqldump
43
64
  end
44
65
 
45
66
  ##
46
- # Performs the mysqldump command and outputs the dump file
47
- # in the +dump_path+ using +dump_filename+.
67
+ # Performs the mysqldump or innobackupex command and outputs
68
+ # the dump file in the +dump_path+ using +dump_filename+.
48
69
  #
49
- # <trigger>/databases/MySQL[-<database_id>].sql[.gz]
70
+ # <trigger>/databases/MySQL[-<database_id>].[sql|tar][.gz]
50
71
  def perform!
51
72
  super
52
73
 
53
74
  pipeline = Pipeline.new
54
- dump_ext = 'sql'
75
+ dump_ext = sql_backup? ? 'sql' : 'tar'
55
76
 
56
- pipeline << mysqldump
77
+ pipeline << sudo_option(sql_backup? ? mysqldump : innobackupex)
57
78
 
58
79
  model.compressor.compress_with do |command, ext|
59
80
  pipeline << command
@@ -81,8 +102,8 @@ module Backup
81
102
 
82
103
  def credential_options
83
104
  opts = []
84
- opts << "--user='#{ username }'" if username
85
- opts << "--password='#{ password }'" if password
105
+ opts << "--user=#{ Shellwords.escape(username) }" if username
106
+ opts << "--password=#{ Shellwords.escape(password) }" if password
86
107
  opts.join(' ')
87
108
  end
88
109
 
@@ -99,6 +120,10 @@ module Backup
99
120
  Array(additional_options).join(' ')
100
121
  end
101
122
 
123
+ def user_prepare_options
124
+ Array(prepare_options).join(' ')
125
+ end
126
+
102
127
  def name_option
103
128
  dump_all? ? '--all-databases' : name
104
129
  end
@@ -118,6 +143,39 @@ module Backup
118
143
  name == :all
119
144
  end
120
145
 
146
+ def sql_backup?
147
+ backup_engine.to_sym == :mysqldump
148
+ end
149
+
150
+ def innobackupex
151
+ # Creation phase
152
+ "#{ utility(:innobackupex) } #{ credential_options } " +
153
+ "#{ connectivity_options } #{ user_options } " +
154
+ "--no-timestamp #{ temp_dir } #{ quiet_option } && " +
155
+ # Log applying phase (prepare for restore)
156
+ "#{ utility(:innobackupex) } --apply-log #{ temp_dir } " +
157
+ "#{ user_prepare_options } #{ quiet_option } && " +
158
+ # Move files to tar-ed stream on stdout
159
+ "#{ utility(:tar) } --remove-files -cf - " +
160
+ "-C #{ File.dirname(temp_dir) } #{ File.basename(temp_dir) }"
161
+ end
162
+
163
+ def sudo_option(command_block)
164
+ return command_block unless sudo_user
165
+
166
+ "sudo -s -u #{ sudo_user } -- <<END_OF_SUDO\n" +
167
+ "#{command_block}\n" +
168
+ "END_OF_SUDO\n"
169
+ end
170
+
171
+ def quiet_option
172
+ verbose ? "" : " 2> /dev/null "
173
+ end
174
+
175
+ def temp_dir
176
+ File.join(dump_path, dump_filename + ".bkpdir")
177
+ end
178
+
121
179
  end
122
180
  end
123
181
  end
@@ -45,7 +45,7 @@ module Backup
45
45
  end
46
46
 
47
47
  ##
48
- # Performs the mysqldump command and outputs the dump file
48
+ # Performs the pgdump command and outputs the dump file
49
49
  # in the +dump_path+ using +dump_filename+.
50
50
  #
51
51
  # <trigger>/databases/PostgreSQL[-<database_id>].sql[.gz]
@@ -35,6 +35,19 @@ module Backup
35
35
  # @return [String] Default: 'log'
36
36
  attr_reader :log_path
37
37
 
38
+ ##
39
+ # Backup's logfile in which backup logs can be written
40
+ #
41
+ # As there is already a log_path, this can simply be just a file name
42
+ # that will be created (If not exists) on log_path directory
43
+ #
44
+ # This may also be set on the command line using +--log-file+.
45
+ # If set on the command line, any setting here will be ignored.
46
+ #
47
+ # @param [String]
48
+ # @return [String] Default: 'backup.log'
49
+ attr_reader :log_file
50
+
38
51
  ##
39
52
  # Size in bytes to truncate logfile to before backup jobs are run.
40
53
  #
@@ -89,7 +102,8 @@ module Backup
89
102
  path = File.join(Backup::Config.root_path, path)
90
103
  end
91
104
  FileUtils.mkdir_p(path)
92
- path = File.join(path, 'backup.log')
105
+ log_file = @options.log_file || 'backup.log'
106
+ path = File.join(path, log_file)
93
107
  if File.exist?(path) && !File.writable?(path)
94
108
  raise Error, "Log File at '#{ path }' is not writable"
95
109
  end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ require 'flowdock'
3
+
4
+ module Backup
5
+ module Notifier
6
+ class FlowDock < Base
7
+
8
+ ##
9
+ # The Flowdock API token
10
+ attr_accessor :token
11
+
12
+ ##
13
+ # Who the notification should appear from
14
+ attr_accessor :from_name
15
+
16
+ # Which email the notification should appear from
17
+ attr_accessor :from_email
18
+
19
+ ##
20
+ # source for message
21
+ attr_accessor :source
22
+
23
+ ##
24
+ # Subject for message
25
+ attr_accessor :subject
26
+
27
+ ##
28
+ # tag message in inbox
29
+ attr_accessor :tags
30
+
31
+ ##
32
+ # link for message
33
+ attr_accessor :link
34
+
35
+ def initialize(model, &block)
36
+ super
37
+ instance_eval(&block) if block_given?
38
+
39
+ @subject ||= default_subject
40
+ @source ||= default_source
41
+ @tags ||= []
42
+ end
43
+
44
+ private
45
+
46
+ ##
47
+ # Notify the user of the backup operation results.
48
+ #
49
+ # `status` indicates one of the following:
50
+ #
51
+ # `:success`
52
+ # : The backup completed successfully.
53
+ # : Notification will be sent if `on_success` is `true`.
54
+ #
55
+ # `:warning`
56
+ # : The backup completed successfully, but warnings were logged.
57
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
58
+ #
59
+ # `:failure`
60
+ # : The backup operation failed.
61
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
62
+ #
63
+ def notify!(status)
64
+ @tags += default_tags(status)
65
+ message = "#{ model.label } (#{ model.trigger })"
66
+ send_message(message)
67
+ end
68
+
69
+ # Flowdock::Client will raise an error if unsuccessful.
70
+ def send_message(msg)
71
+ client = Flowdock::Flow.new(:api_token => token, :source => source,
72
+ :from => {:name => from_name, :address => from_email })
73
+
74
+ client.push_to_team_inbox(:subject => subject,
75
+ :content => msg,
76
+ :tags => tags,
77
+ :link => link )
78
+ end
79
+
80
+ # set related tags
81
+ def default_tags(status)
82
+ case status
83
+ when :success then ['#BackupSuccess']
84
+ when :warning then ['#BackupWarning']
85
+ when :failure then ['#BackupFailure']
86
+ end
87
+ end
88
+
89
+
90
+ #set default source
91
+ def default_source
92
+ "Backup #{ model.label }"
93
+ end
94
+
95
+ # set default subject
96
+ def default_subject
97
+ 'Backup Notification'
98
+ end
99
+
100
+ end
101
+ end
102
+ end
@@ -12,6 +12,10 @@ module Backup
12
12
  # Port of Nagios server to notify on backup completion.
13
13
  attr_accessor :nagios_port
14
14
 
15
+ ##
16
+ # Nagios nrpe configuration file.
17
+ attr_accessor :send_nsca_cfg
18
+
15
19
  ##
16
20
  # Name of the Nagios service for the backup check.
17
21
  attr_accessor :service_name
@@ -26,6 +30,7 @@ module Backup
26
30
 
27
31
  @nagios_host ||= Config.hostname
28
32
  @nagios_port ||= 5667
33
+ @send_nsca_cfg||= "/etc/nagios/send_nsca.cfg"
29
34
  @service_name ||= "Backup #{ model.trigger }"
30
35
  @service_host ||= Config.hostname
31
36
  end
@@ -59,7 +64,7 @@ module Backup
59
64
  end
60
65
 
61
66
  def send_message(message)
62
- cmd = "#{ utility(:send_nsca) } -H '#{ nagios_host }' -p '#{ nagios_port }'"
67
+ cmd = "#{ utility(:send_nsca) } -H '#{ nagios_host }' -p '#{ nagios_port }' -c '#{ send_nsca_cfg }'"
63
68
  msg = [service_host, service_name, model.exit_status, message].join("\t")
64
69
  run("echo '#{ msg }' | #{ cmd }")
65
70
  end
@@ -49,14 +49,13 @@ module Backup
49
49
 
50
50
  # Twitter::Client will raise an error if unsuccessful.
51
51
  def send_message(message)
52
- ::Twitter.configure do |config|
53
- config.consumer_key = @consumer_key
54
- config.consumer_secret = @consumer_secret
55
- config.oauth_token = @oauth_token
56
- config.oauth_token_secret = @oauth_token_secret
52
+ client = ::Twitter::REST::Client.new do |config|
53
+ config.consumer_key = @consumer_key
54
+ config.consumer_secret = @consumer_secret
55
+ config.access_token = @oauth_token
56
+ config.access_token_secret = @oauth_token_secret
57
57
  end
58
58
 
59
- client = ::Twitter::Client.new
60
59
  client.update(message)
61
60
  end
62
61
 
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Notifier
5
+ class Zabbix < Base
6
+
7
+ attr_accessor :zabbix_host
8
+
9
+ attr_accessor :zabbix_port
10
+
11
+ attr_accessor :service_name
12
+
13
+ attr_accessor :service_host
14
+
15
+ attr_accessor :item_key
16
+
17
+ def initialize(model, &block)
18
+ super
19
+ instance_eval(&block) if block_given?
20
+
21
+ @zabbix_host ||= Config.hostname
22
+ @zabbix_port ||= 10051
23
+ @service_name ||= "Backup #{ model.trigger }"
24
+ @service_host ||= Config.hostname
25
+ @item_key ||= 'backup_status'
26
+ end
27
+
28
+ private
29
+
30
+ ##
31
+ # Notify the user of the backup operation results.
32
+ #
33
+ # `status` indicates one of the following:
34
+ #
35
+ # `:success`
36
+ # : The backup completed successfully.
37
+ # : Notification will be sent if `on_success` is `true`.
38
+ #
39
+ # `:warning`
40
+ # : The backup completed successfully, but warnings were logged.
41
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
42
+ #
43
+ # `:failure`
44
+ # : The backup operation failed.
45
+ # : Notification will be sent if `on_warning` or `on_success` is `true`.
46
+ #
47
+ def notify!(status)
48
+ message = case status
49
+ when :success then 'Completed Successfully'
50
+ when :warning then 'Completed Successfully (with Warnings)'
51
+ when :failure then 'Failed'
52
+ end
53
+ send_message("#{ message } in #{ model.duration }")
54
+ end
55
+
56
+ def send_message(message)
57
+ msg = [service_host, service_name, model.exit_status, message].join("\t")
58
+ cmd = "#{ utility(:zabbix_sender) }" +
59
+ " -z '#{ zabbix_host }'" +
60
+ " -p '#{ zabbix_port }'" +
61
+ " -s #{ service_host }" +
62
+ " -k #{ item_key }" +
63
+ " -o '#{ msg }'"
64
+ run("echo '#{ msg }' | #{ cmd }")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -8,11 +8,13 @@ module Backup
8
8
  NAMES = %w{
9
9
  tar cat split sudo chown hostname
10
10
  gzip bzip2
11
- mongo mongodump mysqldump pg_dump pg_dumpall redis-cli riak-admin
11
+ mongo mongodump mysqldump innobackupex
12
+ pg_dump pg_dumpall redis-cli riak-admin
12
13
  gpg openssl
13
14
  rsync ssh
14
15
  sendmail exim
15
16
  send_nsca
17
+ zabbix_sender
16
18
  }
17
19
 
18
20
  module DSL
@@ -94,6 +96,7 @@ module Backup
94
96
  # sendmail '/path/to/sendmail'
95
97
  # exim '/path/to/exim'
96
98
  # send_nsca '/path/to/send_nsca'
99
+ # zabbix_sender '/path/to/zabbix_sender'
97
100
  # end
98
101
  #
99
102
  # These paths may be set using absolute paths, or relative to the
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Backup
4
- VERSION = '4.0.2'
4
+ VERSION = '4.0.3'
5
5
  end
@@ -0,0 +1,15 @@
1
+ ##
2
+ # Zabbix [Notifier]
3
+ #
4
+ notify_by Zabbix do |zabbix|
5
+ zabbix.on_success = true
6
+ zabbix.on_warning = true
7
+ zabbix.on_failure = true
8
+
9
+ zabbix.zabbix_host = "zabbix_server_hostname"
10
+ zabbix.zabbix_port = 10051
11
+ zabbix.service_name = "Backup trigger"
12
+ zabbix.service_host = "zabbix_host"
13
+ zabbix.item_key = "backup_status"
14
+ end
15
+
@@ -0,0 +1,16 @@
1
+ ##
2
+ # Flowdock [Notifier]
3
+ #
4
+ notify_by FlowDock do |flowdock|
5
+ flowdock.on_success = true
6
+ flowdock.on_warning = true
7
+ flowdock.on_failure = true
8
+
9
+ flowdock.token = "token"
10
+ flowdock.from_name = 'my_name'
11
+ flowdock.from_email = 'email@example.com'
12
+ flowdock.subject = 'My Daily Backup'
13
+ flowdock.source = 'Backup'
14
+ flowdock.tags = ['prod', 'backup']
15
+ flowdock.link = 'www.example.com'
16
+ end
@@ -0,0 +1,23 @@
1
+ ##
2
+ # Slack [Notifier]
3
+ #
4
+ notify_by Slack do |slack|
5
+ slack.on_success = true
6
+ slack.on_warning = true
7
+ slack.on_failure = true
8
+
9
+ # The team name
10
+ slack.team = 'my_team'
11
+
12
+ # The integration token
13
+ slack.token = 'xxxxxxxxxxxxxxxxxxxxxxxx'
14
+
15
+ ##
16
+ # Optional
17
+ #
18
+ # The channel to which messages will be sent
19
+ # slack.channel = 'my_channel'
20
+ #
21
+ # The username to display along with the notification
22
+ # slack.username = 'my_username'
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.2
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael van Rooijen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-16 00:00:00.000000000 Z
11
+ date: 2014-08-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.8.8
139
+ - !ruby/object:Gem::Dependency
140
+ name: flowdock
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '='
144
+ - !ruby/object:Gem::Version
145
+ version: 0.4.0
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '='
151
+ - !ruby/object:Gem::Version
152
+ version: 0.4.0
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: fog
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -576,6 +590,7 @@ files:
576
590
  - lib/backup/model.rb
577
591
  - lib/backup/notifier/base.rb
578
592
  - lib/backup/notifier/campfire.rb
593
+ - lib/backup/notifier/flowdock.rb
579
594
  - lib/backup/notifier/hipchat.rb
580
595
  - lib/backup/notifier/http_post.rb
581
596
  - lib/backup/notifier/mail.rb
@@ -584,6 +599,7 @@ files:
584
599
  - lib/backup/notifier/pushover.rb
585
600
  - lib/backup/notifier/slack.rb
586
601
  - lib/backup/notifier/twitter.rb
602
+ - lib/backup/notifier/zabbix.rb
587
603
  - lib/backup/package.rb
588
604
  - lib/backup/packager.rb
589
605
  - lib/backup/pipeline.rb
@@ -624,13 +640,16 @@ files:
624
640
  - templates/cli/encryptor/gpg
625
641
  - templates/cli/encryptor/openssl
626
642
  - templates/cli/model
643
+ - templates/cli/notifier/zabbix
627
644
  - templates/cli/notifiers/campfire
645
+ - templates/cli/notifiers/flowdock
628
646
  - templates/cli/notifiers/hipchat
629
647
  - templates/cli/notifiers/http_post
630
648
  - templates/cli/notifiers/mail
631
649
  - templates/cli/notifiers/nagios
632
650
  - templates/cli/notifiers/prowl
633
651
  - templates/cli/notifiers/pushover
652
+ - templates/cli/notifiers/slack
634
653
  - templates/cli/notifiers/twitter
635
654
  - templates/cli/splitter
636
655
  - templates/cli/storages/cloud_files