Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'develop'

  • Loading branch information...
commit e9ee30cfc1714b9d1eeb78a2b17753f411bce82f 2 parents db86fec + e23c1ea
@meskyanichi meskyanichi authored
View
6 Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- backup (3.0.22)
+ backup (3.0.23)
POpen4 (~> 0.1.4)
thor (~> 0.14.6)
@@ -54,7 +54,7 @@ GEM
i18n (0.6.0)
json (1.5.4)
libnotify (0.7.1)
- mail (2.3.0)
+ mail (2.4.1)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -116,7 +116,7 @@ DEPENDENCIES
httparty (~> 0.7.4)
json (~> 1.5.1)
libnotify
- mail (>= 2.2.15)
+ mail (>= 2.4.0)
mocha
net-scp (~> 1.0.4)
net-sftp (~> 2.0.5)
View
64 README.md
@@ -1,5 +1,5 @@
-Backup 3
-========
+Backup
+======
Backup is a RubyGem, written for Linux and Mac OSX, that allows you to easily perform backup operations on both your remote and local environments. It provides you with an elegant DSL in Ruby for modeling your backups. Backup has built-in support for various databases, storage protocols/services, syncers, compressors, encryptors and notifiers which you can mix and match. It was built with modularity, extensibility and simplicity in mind.
@@ -7,16 +7,14 @@ Backup is a RubyGem, written for Linux and Mac OSX, that allows you to easily pe
[![Still Maintained](http://stillmaintained.com/meskyanichi/backup.png)](http://stillmaintained.com/meskyanichi/backup)
-Author
-------
+### Author
**[Michael van Rooijen](http://michaelvanrooijen.com/) ( [@meskyanichi](http://twitter.com/#!/meskyanichi) )**
Drop me a message for any questions, suggestions, requests, bugs or submit them to the [issue log](https://github.com/meskyanichi/backup/issues).
-Installation
-------------
+### Installation
To get the latest stable version
@@ -25,18 +23,16 @@ To get the latest stable version
You can view the list of released versions over at [RubyGems.org (Backup)](https://rubygems.org/gems/backup/versions)
-Getting Started
----------------
+### Getting Started
I recommend you read this README first, and refer to the [wiki pages](https://github.com/meskyanichi/backup/wiki) afterwards. There's also a [Getting Started wiki page](https://github.com/meskyanichi/backup/wiki/Getting-Started).
What Backup 3 currently supports
-================================
+--------------------------------
Below you find a list of components that Backup currently supports. If you'd like support for components other than the ones listed here, feel free to request them or to fork Backup and add them yourself. Backup is modular and easy to extend.
-Database Support
-----------------
+### Database Support
- MySQL
- PostgreSQL
@@ -46,16 +42,14 @@ Database Support
[Database Wiki Page](https://github.com/meskyanichi/backup/wiki/Databases)
-Filesystem Support
-------------------
+### Filesystem Support
- Files
- Directories
[Archive Wiki Page](https://github.com/meskyanichi/backup/wiki/Archives)
-Storage Locations and Services
-------------------------------
+### Storage Locations and Services
- Amazon Simple Storage Service (S3)
- Rackspace Cloud Files (Mosso)
@@ -66,8 +60,7 @@ Storage Locations and Services
[Storage Wiki Page](https://github.com/meskyanichi/backup/wiki/Storages)
-Storage Features
-----------------
+### Storage Features
- **Backup Cycling, applies to:**
- Amazon Simple Storage Service (S3)
@@ -90,8 +83,7 @@ Storage Features
[Splitter Wiki Page](https://github.com/meskyanichi/backup/wiki/Splitter)
-Syncers
--------
+### Syncers
- RSync (Push, Pull and Local)
- Amazon S3
@@ -99,8 +91,7 @@ Syncers
[Syncer Wiki Page](https://github.com/meskyanichi/backup/wiki/Syncers)
-Compressors
------------
+### Compressors
- Gzip
- Bzip2
@@ -109,16 +100,14 @@ Compressors
[Compressors Wiki Page](https://github.com/meskyanichi/backup/wiki/Compressors)
-Encryptors
-----------
+### Encryptors
- OpenSSL
- GPG
[Encryptors Wiki Page](https://github.com/meskyanichi/backup/wiki/Encryptors)
-Notifiers
----------
+### Notifiers
- Mail
- Twitter
@@ -129,8 +118,7 @@ Notifiers
[Notifiers Wiki Page](https://github.com/meskyanichi/backup/wiki/Notifiers)
-Supported Ruby versions (Tested with RSpec)
--------------------------------------------
+### Supported Ruby versions (Tested with RSpec)
- Ruby 1.9.3
- Ruby 1.9.2
@@ -138,7 +126,7 @@ Supported Ruby versions (Tested with RSpec)
A sample Backup configuration file
-==================================
+----------------------------------
This is a Backup configuration file. Check it out and read the explanation below. Backup has a [great wiki](https://github.com/meskyanichi/backup/wiki) which explains each component of Backup in detail.
@@ -302,19 +290,16 @@ With this in place, run `whenever --update-crontab backup` to write the equivale
crontab in cron-syntax. Cron will now invoke `backup perform --trigger sample_backup` every 6 hours. Check out the
Whenever project page for more information.
-Documentation
--------------
+### Documentation
See the [Wiki Pages](https://github.com/meskyanichi/backup/wiki).
-Suggestions, Bugs, Requests, Questions
---------------------------------------
+### Suggestions, Bugs, Requests, Questions
View the [issue log](https://github.com/meskyanichi/backup/issues) and post them there.
-Contributors
-------------
+### Contributors
<table>
<tr>
@@ -444,8 +429,7 @@ Contributors
</table>
-Want to contribute?
--------------------
+### Want to contribute?
- Fork/Clone the **develop** branch
- Write RSpec tests, and test against:
@@ -456,8 +440,8 @@ Want to contribute?
I can't guarantee I'll pull every pull request. Also, I may accept your pull request and drastically change parts to improve readability/maintainability. Feel free to discuss about improvements, new functionality/features in the [issue log](https://github.com/meskyanichi/backup/issues) before contributing if you need/want more information.
-Easily run tests against all three Ruby versions
-------------------------------------------------
+
+### Easily run tests against all three Ruby versions
Install [RVM](https://rvm.beginrescueend.com/) and use it to install Ruby 1.9.3, 1.9.2 and 1.8.7.
@@ -478,9 +462,9 @@ The Backup gem uses [Guard](https://github.com/guard/guard) along with [Guard::R
from Backup's root and that's it. It'll now test against all Ruby versions each time you adjust a file in the `lib` or `spec` directories.
-Or contribute by writing blogs/tutorials/use cases
---------------------------------------------------
+### Or contribute by writing blogs/tutorials/use cases
+- http://freelancing-gods.com/posts/backing_up_with_backup
- http://erik.debill.org/2011/03/26/csing-backup-with-rails
- http://blog.noizeramp.com/2011/03/31/backing-up-backup-ruby-gem/
- http://www.sebaugereau.com/using-ruby-to-backup-with-beauty
View
3  lib/backup/configuration/database/mysql.rb
@@ -7,7 +7,8 @@ class MySQL < Base
class << self
##
- # Name of the database that needs to get dumped
+ # Name of the database that needs to get dumped.
+ # To dump all databases, set this to `:all` or leave blank.
attr_accessor :name
##
View
17 lib/backup/configuration/notifier/mail.rb
@@ -19,6 +19,10 @@ class << self
# : Settings used only by this method:
# : `sendmail`, `sendmail_args`
#
+ # `:exim` [::Mail::Exim]
+ # : Settings used only by this method:
+ # : `exim`, `exim_args`
+ #
# `:file` [::Mail::FileDelivery]
# : Settings used only by this method:
# : `mail_folder`
@@ -83,6 +87,19 @@ class << self
attr_accessor :sendmail_args
##
+ # When using the `:exim` `delivery_method` option,
+ # this may be used to specify the absolute path to `exim` (if needed)
+ # Example: '/usr/sbin/exim'
+ attr_accessor :exim
+
+ ##
+ # Optional arguments to pass to `exim`
+ # Note that this will override the defaults set by the Mail gem (currently: '-i -t')
+ # So, if set here, be sure to set all the arguments you require.
+ # Example: '-i -t -X/tmp/traffic.log'
+ attr_accessor :exim_args
+
+ ##
# Folder where mail will be kept when using the `:file` `delivery_method` option.
# Default location is '$HOME/backup-mails'
# Example: '/tmp/test-mails'
View
33 lib/backup/database/mysql.rb
@@ -6,6 +6,7 @@ class MySQL < Base
##
# Name of the database that needs to get dumped
+ # To dump all databases, set this to `:all` or leave blank.
attr_accessor :name
##
@@ -43,6 +44,8 @@ def initialize(model, &block)
instance_eval(&block) if block_given?
+ @name ||= :all
+
if @utility_path
Logger.warn "[DEPRECATED] " +
"Database::MySQL#utility_path has been deprecated.\n" +
@@ -68,7 +71,7 @@ def perform!
end
end
- dump_cmd << " > '#{ File.join(@dump_path, name) }.#{ dump_ext }'"
+ dump_cmd << " > '#{ File.join(@dump_path, dump_filename) }.#{ dump_ext }'"
run(dump_cmd)
end
@@ -78,7 +81,13 @@ def perform!
# Builds the full mysqldump string based on all attributes
def mysqldump
"#{ mysqldump_utility } #{ credential_options } #{ connectivity_options } " +
- "#{ user_options } #{ name } #{ tables_to_dump } #{ tables_to_skip }"
+ "#{ user_options } #{ db_name } #{ tables_to_dump } #{ tables_to_skip }"
+ end
+
+ ##
+ # Returns the filename to use for dumping the database(s)
+ def dump_filename
+ dump_all? ? 'all-databases' : name
end
##
@@ -109,10 +118,18 @@ def user_options
end
##
+ # Returns the database name to use in the mysqldump command.
+ # When dumping all databases, the database name is replaced
+ # with the command option to dump all databases.
+ def db_name
+ dump_all? ? '--all-databases' : name
+ end
+
+ ##
# Builds the MySQL syntax for specifying which tables to dump
# during the dumping of the database
def tables_to_dump
- only_tables.join(' ')
+ only_tables.join(' ') unless dump_all?
end
##
@@ -121,7 +138,15 @@ def tables_to_dump
def tables_to_skip
skip_tables.map do |table|
"--ignore-table='#{name}.#{table}'"
- end.join(' ')
+ end.join(' ') unless dump_all?
+ end
+
+ ##
+ # Return true if we're dumping all databases.
+ # `name` will be set to :all if it is not set,
+ # so this will be true by default
+ def dump_all?
+ name == :all
end
end
View
2  lib/backup/dependency.rb
@@ -47,7 +47,7 @@ def self.all
'mail' => {
:require => 'mail',
- :version => '>= 2.2.15',
+ :version => '>= 2.4.0',
:for => 'Sending Emails (Mail Notifier)'
},
View
2  lib/backup/logger.rb
@@ -62,6 +62,8 @@ def clear!
def truncate!(max_bytes = 500_000)
log_file = File.join(Config.log_path, 'backup.log')
+ return unless File.exist?(log_file)
+
if File.stat(log_file).size > max_bytes
FileUtils.mv(log_file, log_file + '~')
File.open(log_file + '~', 'r') do |io_in|
View
24 lib/backup/notifier/mail.rb
@@ -21,6 +21,10 @@ class Mail < Base
# : Settings used only by this method:
# : `sendmail`, `sendmail_args`
#
+ # `:exim` [::Mail::Exim]
+ # : Settings used only by this method:
+ # : `exim`, `exim_args`
+ #
# `:file` [::Mail::FileDelivery]
# : Settings used only by this method:
# : `mail_folder`
@@ -85,6 +89,19 @@ class Mail < Base
attr_accessor :sendmail_args
##
+ # When using the `:exim` `delivery_method` option,
+ # this may be used to specify the absolute path to `exim` (if needed)
+ # Example: '/usr/sbin/exim'
+ attr_accessor :exim
+
+ ##
+ # Optional arguments to pass to `exim`
+ # Note that this will override the defaults set by the Mail gem (currently: '-i -t')
+ # So, if set here, be sure to set all the arguments you require.
+ # Example: '-i -t -X/tmp/traffic.log'
+ attr_accessor :exim_args
+
+ ##
# Folder where mail will be kept when using the `:file` `delivery_method` option.
# Default location is '$HOME/Backup/emails'
# Example: '/tmp/test-mails'
@@ -144,7 +161,7 @@ def notify!(status)
# Configures the Mail gem by setting the defaults.
# Creates and returns a new email, based on the @delivery_method used.
def new_email
- method = %w{ smtp sendmail file test }.
+ method = %w{ smtp sendmail exim file test }.
index(@delivery_method.to_s) ? @delivery_method.to_s : 'smtp'
options =
@@ -163,6 +180,11 @@ def new_email
opts.merge!(:location => File.expand_path(@sendmail)) if @sendmail
opts.merge!(:arguments => @sendmail_args) if @sendmail_args
opts
+ when 'exim'
+ opts = {}
+ opts.merge!(:location => File.expand_path(@exim)) if @exim
+ opts.merge!(:arguments => @exim_args) if @exim_args
+ opts
when 'file'
@mail_folder ||= File.join(Config.root_path, 'emails')
{ :location => File.expand_path(@mail_folder) }
View
2  lib/backup/version.rb
@@ -13,7 +13,7 @@ class Version
# Defines the minor version
# PATCH:
# Defines the patch version
- MAJOR, MINOR, PATCH = 3, 0, 22
+ MAJOR, MINOR, PATCH = 3, 0, 23
##
# Returns the major version ( big release based off of multiple minor releases )
View
6 spec/configuration/notifier/mail_spec.rb
@@ -18,6 +18,8 @@
mail.openssl_verify_mode = 'none'
mail.sendmail = '/path/to/sendmail'
mail.sendmail_args = '-i -t -X/tmp/traffic.log'
+ mail.exim = '/path/to/exim'
+ mail.exim_args = '-i -t -X/tmp/traffic.log'
mail.mail_folder = '/path/to/backup/mails'
end
end
@@ -38,6 +40,8 @@
mail.openssl_verify_mode.should == 'none'
mail.sendmail.should == '/path/to/sendmail'
mail.sendmail_args.should == '-i -t -X/tmp/traffic.log'
+ mail.exim.should == '/path/to/exim'
+ mail.exim_args.should == '-i -t -X/tmp/traffic.log'
mail.mail_folder.should == '/path/to/backup/mails'
end
@@ -59,6 +63,8 @@
mail.openssl_verify_mode.should == nil
mail.sendmail.should == nil
mail.sendmail_args.should == nil
+ mail.exim.should == nil
+ mail.exim_args.should == nil
mail.mail_folder.should == nil
end
end
View
82 spec/database/mysql_spec.rb
@@ -44,7 +44,7 @@
it 'should use default values' do
db = Backup::Database::MySQL.new(model)
- db.name.should be_nil
+ db.name.should == :all
db.username.should be_nil
db.password.should be_nil
db.host.should be_nil
@@ -101,6 +101,7 @@
db.instance_variable_set(:@dump_path, '/dump/path')
db.stubs(:mysqldump).returns('mysqldump_command')
+ db.stubs(:dump_filename).returns('dump_filename')
end
context 'when no compressor is configured' do
@@ -110,7 +111,7 @@
it 'should run mysqldump without compression' do
db.expects(:run).in_sequence(s).with(
- "mysqldump_command > '/dump/path/mydatabase.sql'"
+ "mysqldump_command > '/dump/path/dump_filename.sql'"
)
db.perform!
end
@@ -125,7 +126,7 @@
it 'should run mysqldump with compression' do
db.expects(:run).in_sequence(s).with(
- "mysqldump_command | gzip > '/dump/path/mydatabase.sql.gz'"
+ "mysqldump_command | gzip > '/dump/path/dump_filename.sql.gz'"
)
db.perform!
end
@@ -134,12 +135,35 @@
end # describe '#perform!'
describe '#mysqldump' do
+ before do
+ db.stubs(:mysqldump_utility).returns(:mysqldump_utility)
+ db.stubs(:credential_options).returns(:credential_options)
+ db.stubs(:connectivity_options).returns(:connectivity_options)
+ db.stubs(:user_options).returns(:user_options)
+ db.stubs(:db_name).returns(:db_name)
+ db.stubs(:tables_to_dump).returns(:tables_to_dump)
+ db.stubs(:tables_to_skip).returns(:tables_to_skip)
+ end
+
it 'should return the mysqldump command string' do
db.send(:mysqldump).should ==
- "/path/to/mysqldump --user='someuser' --password='secret' " +
- "--host='localhost' --port='123' --socket='/mysql.sock' " +
- "--single-transaction --quick mydatabase users pirates " +
- "--ignore-table='mydatabase.logs' --ignore-table='mydatabase.profiles'"
+ "mysqldump_utility credential_options connectivity_options " +
+ "user_options db_name tables_to_dump tables_to_skip"
+ end
+ end
+
+ describe '#dump_filename' do
+ context 'when @name is set to :all' do
+ before { db.name = :all }
+ it 'should set the filename to "all-databases"' do
+ db.send(:dump_filename).should == 'all-databases'
+ end
+ end
+
+ context 'when @name is not set to :all' do
+ it 'should return @name' do
+ db.send(:dump_filename).should == 'mydatabase'
+ end
end
end
@@ -196,6 +220,21 @@
end
end
+ describe '#db_name' do
+ context 'when @name is set to :all' do
+ before { db.name = :all }
+ it 'should return the mysqldump flag to dump all databases' do
+ db.send(:db_name).should == '--all-databases'
+ end
+ end
+
+ context 'when @name is not set to :all' do
+ it 'should return @name' do
+ db.send(:db_name).should == 'mydatabase'
+ end
+ end
+ end
+
describe '#tables_to_dump' do
it 'should return a string for the mysqldump selected table to dump option' do
db.send(:tables_to_dump).should == 'users pirates'
@@ -207,6 +246,13 @@
db.send(:tables_to_dump).should == ''
end
end
+
+ context 'when dump_all? is true' do
+ before { db.stubs(:dump_all?).returns(true) }
+ it 'should return nil' do
+ db.send(:tables_to_dump).should be_nil
+ end
+ end
end
describe '#tables_to_skip' do
@@ -221,5 +267,27 @@
db.send(:tables_to_skip).should == ''
end
end
+
+ context 'when dump_all? is true' do
+ before { db.stubs(:dump_all?).returns(true) }
+ it 'should return nil' do
+ db.send(:tables_to_skip).should be_nil
+ end
+ end
+ end
+
+ describe '#dump_all?' do
+ context 'when @name is set to :all' do
+ before { db.name = :all }
+ it 'should return true' do
+ db.send(:dump_all?).should be_true
+ end
+ end
+
+ context 'when @name is not set to :all' do
+ it 'should return false' do
+ db.send(:dump_all?).should be_false
+ end
+ end
end
end
View
16 spec/logger_spec.rb
@@ -145,13 +145,23 @@
end # describe '#clear!'
describe '#truncate!' do
+ context 'when log file does not exist' do
+ before { File.stubs(:exist?).returns(false) }
+ it 'should do nothing' do
+ File.expects(:stat).never
+ subject.truncate!
+ end
+ end
+
context 'when log file is <= max_bytes' do
+ before { File.stubs(:exist?).returns(true) }
it 'should do nothing' do
stat = mock
+ File.expects(:stat).twice.with(
+ File.join(Backup::Config.log_path, 'backup.log')
+ ).returns(stat)
+
[1, 2].each do |size|
- File.expects(:stat).with(
- File.join(Backup::Config.log_path, 'backup.log')
- ).returns(stat)
stat.expects(:size).returns(size)
FileUtils.expects(:mv).never
View
25 spec/notifier/mail_spec.rb
@@ -19,6 +19,8 @@
mail.sendmail = '/path/to/sendmail'
mail.sendmail_args = '-i -t -X/tmp/traffic.log'
+ mail.exim = '/path/to/exim'
+ mail.exim_args = '-i -t -X/tmp/traffic.log'
mail.mail_folder = '/path/to/backup/mails'
end
@@ -40,6 +42,8 @@
notifier.sendmail.should == '/path/to/sendmail'
notifier.sendmail_args.should == '-i -t -X/tmp/traffic.log'
+ notifier.exim.should == '/path/to/exim'
+ notifier.exim_args.should == '-i -t -X/tmp/traffic.log'
notifier.mail_folder.should == '/path/to/backup/mails'
@@ -73,6 +77,8 @@
notifier.sendmail.should be_nil
notifier.sendmail_args.should be_nil
+ notifier.exim.should be_nil
+ notifier.exim_args.should be_nil
notifier.mail_folder.should be_nil
@@ -233,6 +239,25 @@
end
end
+ context 'when delivery_method is :exim' do
+ before { notifier.delivery_method = :exim }
+ it 'should return an email using Exim' do
+ email = notifier.send(:new_email)
+ email.delivery_method.should be_an_instance_of ::Mail::Exim
+ end
+
+ it 'should set the proper options' do
+ email = notifier.send(:new_email)
+
+ email.to.should == ['my.receiver.email@gmail.com']
+ email.from.should == ['my.sender.email@gmail.com']
+
+ settings = email.delivery_method.settings
+ settings[:location].should == '/path/to/exim'
+ settings[:arguments].should == '-i -t -X/tmp/traffic.log'
+ end
+ end
+
context 'when delivery_method is :file' do
before { notifier.delivery_method = :file }
it 'should return an email using FileDelievery' do
View
1  templates/cli/utility/database/mysql
@@ -2,6 +2,7 @@
# MySQL [Database]
#
database MySQL do |db|
+ # To dump all databases, set db.name = :all (or leave blank)
db.name = "my_database_name"
db.username = "my_username"
db.password = "my_password"
Please sign in to comment.
Something went wrong with that request. Please try again.