dreamhost-personal-backup 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ service_name: travis-ci
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+
3
+ notifications:
4
+ disabled: true
5
+
6
+ rvm:
7
+ - 1.9.2
8
+ - 1.9.3
9
+ - 2.0.0
10
+ - jruby
@@ -0,0 +1,4 @@
1
+ = Dreamhost Personal Backup gem CHANGELOG
2
+
3
+ == 0.1.0
4
+ * Initial limited feature release. Includes basic rsync backup, logging, and check for an already-running backup.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rsync'
4
+
5
+ group :test, :development do
6
+ gem 'mocha', :require => false
7
+ gem 'simplecov', :require => false
8
+ gem 'coveralls', :require => false
9
+ gem 'jeweler'
10
+ end
@@ -0,0 +1,78 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.3.5)
5
+ builder (3.2.2)
6
+ coveralls (0.7.0)
7
+ multi_json (~> 1.3)
8
+ rest-client
9
+ simplecov (>= 0.7)
10
+ term-ansicolor
11
+ thor
12
+ docile (1.1.1)
13
+ faraday (0.8.8)
14
+ multipart-post (~> 1.2.0)
15
+ git (1.2.6)
16
+ github_api (0.10.1)
17
+ addressable
18
+ faraday (~> 0.8.1)
19
+ hashie (>= 1.2)
20
+ multi_json (~> 1.4)
21
+ nokogiri (~> 1.5.2)
22
+ oauth2
23
+ hashie (2.0.5)
24
+ highline (1.6.20)
25
+ httpauth (0.2.0)
26
+ jeweler (1.8.8)
27
+ builder
28
+ bundler (~> 1.0)
29
+ git (>= 1.2.5)
30
+ github_api (= 0.10.1)
31
+ highline (>= 1.6.15)
32
+ nokogiri (= 1.5.10)
33
+ rake
34
+ rdoc
35
+ json (1.8.1)
36
+ jwt (0.1.8)
37
+ multi_json (>= 1.5)
38
+ metaclass (0.0.1)
39
+ mime-types (2.0)
40
+ mocha (0.14.0)
41
+ metaclass (~> 0.0.1)
42
+ multi_json (1.8.2)
43
+ multi_xml (0.5.5)
44
+ multipart-post (1.2.0)
45
+ nokogiri (1.5.10)
46
+ oauth2 (0.9.2)
47
+ faraday (~> 0.8)
48
+ httpauth (~> 0.2)
49
+ jwt (~> 0.1.4)
50
+ multi_json (~> 1.0)
51
+ multi_xml (~> 0.5)
52
+ rack (~> 1.2)
53
+ rack (1.5.2)
54
+ rake (10.1.1)
55
+ rdoc (4.1.0)
56
+ json (~> 1.4)
57
+ rest-client (1.6.7)
58
+ mime-types (>= 1.16)
59
+ rsync (1.0.8)
60
+ simplecov (0.8.2)
61
+ docile (~> 1.1.0)
62
+ multi_json
63
+ simplecov-html (~> 0.8.0)
64
+ simplecov-html (0.8.0)
65
+ term-ansicolor (1.2.2)
66
+ tins (~> 0.8)
67
+ thor (0.18.1)
68
+ tins (0.13.1)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ coveralls
75
+ jeweler
76
+ mocha
77
+ rsync
78
+ simplecov
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ ==== Dreamhost Backup Gem License
2
+
3
+ Copyright (c) 2013 Phil Trimble
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,105 @@
1
+ = Dreamhost Personal Backup Gem
2
+
3
+ THIS IS A WORK IN PROGRESS. FEATURES MAY NOT WORK AND DOCUMENTATION MAY NOT BE ACCURATE.
4
+ PLEASE DO NOT USE YET FOR BACKUPS.
5
+
6
+ {<img src="https://travis-ci.org/ptrimble/dreamhost-personal-backup.png" />}[https://travis-ci.org/ptrimble/dreamhost-personal-backup] {<img src="https://coveralls.io/repos/ptrimble/dreamhost-personal-backup/badge.png?branch=master" />}[https://coveralls.io/r/ptrimble/dreamhost-personal-backup]
7
+
8
+ Provides functionality to perform personal backups (on Linux or OSX) to a Dreamhost personal backup server.
9
+
10
+ Dreamhost provides a 'personal backup' that allows you to back up your personal files to
11
+ special Dreamhost backup servers. I use it as an offsite mirror of my personal files (documents,
12
+ music, photos, etc).
13
+
14
+ This backup is a mirror of what is on your home machine. It does not have versioning. If you want to restore from
15
+ backup then you simply copy what is on the Dreamhost server to your home machine.
16
+
17
+ Currently you must set up your own schedule to execute this gem.
18
+
19
+ This gem uses rsync to perform the backups.
20
+
21
+ Dreamhost Personal Backup Wiki: http://wiki.dreamhost.com/Personal_Backup
22
+
23
+ === Usage
24
+
25
+ Install the usual way:
26
+ gem install dreamhost-personal-backup
27
+
28
+ You can then call it from the command line.
29
+ $ dreamhost_personal_backup
30
+
31
+ The gem accepts only one parameter (which is optional): a config file path.
32
+ $ dreamhost_personal_backup '/path/to/you/config/file'
33
+
34
+ Calling without a config file parameter will cause the gem to look for a config file at
35
+ '~/.dreamhost_personal_backup/default_config.yml'. If this file does not exist then an error will be returned.
36
+
37
+ ==== Dreamhost Setup
38
+
39
+ This gem currently assumes that you have activated your Dreamhost Backup User via the Dreamhost Panel and that you
40
+ have set up SSH trust with your backup server.
41
+
42
+ Dreamhost Backup Servers use rssh, which is a restricted shell. As such setting up SSH via their instructions is the
43
+ only way to truly automate backups. See their wiki (http://wiki.dreamhost.com/Personal_Backup) for step-by-step
44
+ instructions on how to set up SSH trust between your host and the backup server.
45
+
46
+ === Configuration
47
+
48
+ This gem can be called either by passing a configuration YAML filepath or by setting up a configuration file in a
49
+ default location. The default location that this gem will reference for a configuration file is
50
+ '~/.dreamhost_personal_backup/default_config.yml'. If this file does not exist and no config file is passed then an
51
+ error will be returned.
52
+
53
+ The following parameters are available:
54
+
55
+ * user (required)
56
+ * host (required)
57
+ * targets (required)
58
+ * logfile (optional, default: STDOUT)
59
+ * logrotationsizeinbytes (optional, default: 105000000)
60
+ * logkeepcount (optional, default: 3)
61
+ * notifyemail (optional, default: nil)
62
+
63
+ Here is an example config file:
64
+
65
+ user: <username>
66
+ host: <host>
67
+
68
+ logfile: ~/logs/backup.log
69
+ logrotationsizeinbytes: 500000000
70
+ logkeepcount: 5
71
+
72
+ notifyemail: target_address@email.com
73
+
74
+ targets:
75
+ music: /media/drive/Music
76
+ documents: ~/Documents
77
+ writing: ~/Writing
78
+ scripts: ~/scripts
79
+ gmail-archive: ~/gmail-archive
80
+ patches: ~/Code/patches
81
+
82
+ ==== cron
83
+
84
+ Tasks with this gem can be scheduled to execute at regular intervals. Example:
85
+
86
+ # Run the backup script every 3 hours every day
87
+ 0 0,3,6,9,12,15,18,22 * * * dreamhost_personal_backup
88
+
89
+ === rsync details
90
+
91
+ The following parameters are used with rsync:
92
+ * Archive (-a) - ensures that all symbolic links, devices, attributes, permissions, ownerships, etc are preserved
93
+ * Verbose (-v) - Shows verbose logging
94
+ * Compress (-z) - Compresses files during transfer
95
+ * Partial/ Progress (-P) - Keeps partially tranferred files and shows progress in the logs
96
+ * Deletes (--delete) - Deletes files on the Dreamhost side that do not exist on the sending side
97
+
98
+ In practice what this means is that it keeps a mirror of what is on the sending side. Deleting a file on the home host
99
+ will remove it from the backup server.
100
+
101
+ === Credits and code
102
+
103
+ * Source: https://github.com/ptrimble/dreamhost-personal-backup
104
+ * Build status: http://travis-ci.org/#!/ptrimble/dreamhost-personal-backup
105
+ * Code Coverage: https://coveralls.io/r/ptrimble/dreamhost-personal-backup
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dreamhost_personal_backup'
4
+
5
+ DreamhostPersonalBackup.perform_backup(ARGV[0])
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in rakefile.rb, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "dreamhost-personal-backup"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Phil Trimble"]
12
+ s.date = "2014-01-15"
13
+ s.description = "Provides functionality to perform personal backups (on Linux or OSX) to a Dreamhost personal backup server."
14
+ s.email = "philtrimble@gmail.com"
15
+ s.executables = ["dreamhost_personal_backup"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".coveralls.yml",
22
+ ".travis.yml",
23
+ "CHANGELOG",
24
+ "Gemfile",
25
+ "Gemfile.lock",
26
+ "LICENSE",
27
+ "README.rdoc",
28
+ "bin/dreamhost_personal_backup",
29
+ "dreamhost-personal-backup.gemspec",
30
+ "lib/backup/backup.rb",
31
+ "lib/backup/configurator.rb",
32
+ "lib/backup/status_manager.rb",
33
+ "lib/dreamhost_personal_backup.rb",
34
+ "rakefile.rb",
35
+ "test/test_backup.rb",
36
+ "test/test_configurator.rb",
37
+ "test/test_dreamhost_personal_backup.rb",
38
+ "test/test_files/test_config_file_missing_optional_params.yml",
39
+ "test/test_files/test_invalid_parameters.yml",
40
+ "test/test_files/test_standard_config_file.yml",
41
+ "test/test_helper.rb",
42
+ "test/test_status_manager.rb"
43
+ ]
44
+ s.homepage = "https://github.com/ptrimble/dreamhost-personal-backup"
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = "1.8.23"
47
+ s.summary = "Provides functionality to perform personal backups (on Linux or OSX) to a Dreamhost personal backup server."
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<rsync>, [">= 0"])
54
+ s.add_development_dependency(%q<mocha>, [">= 0"])
55
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
56
+ s.add_development_dependency(%q<coveralls>, [">= 0"])
57
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
58
+ else
59
+ s.add_dependency(%q<rsync>, [">= 0"])
60
+ s.add_dependency(%q<mocha>, [">= 0"])
61
+ s.add_dependency(%q<simplecov>, [">= 0"])
62
+ s.add_dependency(%q<coveralls>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<rsync>, [">= 0"])
67
+ s.add_dependency(%q<mocha>, [">= 0"])
68
+ s.add_dependency(%q<simplecov>, [">= 0"])
69
+ s.add_dependency(%q<coveralls>, [">= 0"])
70
+ s.add_dependency(%q<jeweler>, [">= 0"])
71
+ end
72
+ end
73
+
@@ -0,0 +1,55 @@
1
+ require 'rsync'
2
+
3
+ module DreamhostPersonalBackup
4
+
5
+ class MissingConfigParameter < StandardError; end
6
+
7
+ module Backup
8
+ RSYNC_COMMAND_ARGS = ['-e ssh', '-avzP', '--delete']
9
+
10
+ def self.run_for_target_directory(target_dir, config_parameters)
11
+ check_for_required_parameters(config_parameters)
12
+
13
+ user = config_parameters[:user]
14
+ host = config_parameters[:host]
15
+ logger = config_parameters[:logger]
16
+
17
+ target_dir = File.expand_path(target_dir)
18
+
19
+ logger.info(" Running backup for target directory: #{target_dir}")
20
+
21
+ rsync_result = Rsync.run(target_dir, "#{user}@#{host}:~/", RSYNC_COMMAND_ARGS)
22
+
23
+ log_rsync_result(rsync_result, logger)
24
+
25
+ rsync_result.success?
26
+ end
27
+
28
+ private
29
+
30
+ def self.check_for_required_parameters(config_parameters)
31
+ raise MissingConfigParameter if config_parameters[:user].nil?
32
+ raise MissingConfigParameter if config_parameters[:host].nil?
33
+ raise MissingConfigParameter if config_parameters[:logger].nil?
34
+ end
35
+
36
+ def self.log_rsync_result(rsync_result, logger)
37
+ if rsync_result.success?
38
+ if rsync_result.changes.count > 0
39
+ logger.info(" Results:")
40
+
41
+ rsync_result.changes.each do |change|
42
+ logger.info " #{change.summary} - #{change.filename}"
43
+ end
44
+ else
45
+ logger.info(" No changes took place!")
46
+ end
47
+
48
+ logger.info(" Backup completed successfully")
49
+ else
50
+ logger.error(" Backup failed, error: #{rsync_result.error}")
51
+ end
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,59 @@
1
+ require 'yaml'
2
+ require 'logger'
3
+
4
+ module DreamhostPersonalBackup
5
+
6
+ class ConfigFileNotFound < StandardError; end
7
+ class InvalidConfigParameter < StandardError; end
8
+
9
+ class Configurator
10
+
11
+ VALID_CONFIG_PARAMETERS = [:user, :host, :logfile, :targets, :notifyemail, :logrotationsizeinbytes, :logkeepcount]
12
+
13
+ DEFAULT_CONFIG_FILE = '~/.dreamhost_personal_backup/default_config.yml'
14
+ DEFAULT_LOG_SIZE = 105000000
15
+ DEFAULT_LOG_KEEP_COUNT = 3
16
+
17
+ def self.process_config_file(config_file_path = nil)
18
+ config_file_path ||= DEFAULT_CONFIG_FILE
19
+ config_file = File.expand_path(config_file_path)
20
+
21
+ raise DreamhostPersonalBackup::ConfigFileNotFound unless File.file?(config_file)
22
+
23
+ config_parameters = Hash.new
24
+
25
+ config_file = YAML.load_file(config_file)
26
+ config_file.each do |config_key, config_value|
27
+ config_parameter = config_key.downcase.to_sym
28
+
29
+ raise DreamhostPersonalBackup::InvalidConfigParameter unless VALID_CONFIG_PARAMETERS.include?(config_parameter)
30
+
31
+ config_parameters[config_parameter] = config_value
32
+ end
33
+
34
+ config_parameters = set_default_values_if_necessary(config_parameters)
35
+
36
+ config_parameters[:logger] = create_logger(config_parameters)
37
+
38
+ config_parameters
39
+ end
40
+
41
+ private
42
+
43
+ def self.set_default_values_if_necessary(config_parameters)
44
+ config_parameters[:logrotationsizeinbytes] = DEFAULT_LOG_SIZE unless config_parameters.has_key?(:logrotationsizeinbytes)
45
+ config_parameters[:logkeepcount] = DEFAULT_LOG_KEEP_COUNT unless config_parameters.has_key?(:logkeepcount)
46
+
47
+ config_parameters
48
+ end
49
+
50
+ def self.create_logger(config_parameters)
51
+ logfile = File.expand_path(config_parameters[:logfile]) unless config_parameters[:logfile].nil?
52
+ logfile = STDOUT if logfile.nil?
53
+
54
+ Logger.new(logfile,
55
+ shift_age = config_parameters[:logkeepcount],
56
+ shift_size = config_parameters[:logrotationsizeinbytes])
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,31 @@
1
+ module DreamhostPersonalBackup
2
+
3
+ module StatusManager
4
+
5
+ PID_FILE = '~/.dreamhost_personal_backup/running.pid'
6
+
7
+ def self.is_backup_running?
8
+ pid_file = File.expand_path(PID_FILE)
9
+ return false unless File.file?(pid_file)
10
+
11
+ pid = File.open(pid_file).read.to_i
12
+
13
+ begin
14
+ Process.getpgid(pid)
15
+ return true
16
+ rescue Errno::ESRCH
17
+ return false
18
+ end
19
+ end
20
+
21
+ def self.create_pid_file
22
+ File.open(File.expand_path(PID_FILE), "w") { |f| f.write(Process.pid) }
23
+ end
24
+
25
+ def self.remove_pid_file
26
+ pid_file = File.expand_path(PID_FILE)
27
+ File.delete(pid_file) if File.file?(pid_file)
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ require 'backup/configurator'
2
+ require 'backup/backup'
3
+ require 'backup/status_manager'
4
+
5
+ module DreamhostPersonalBackup
6
+ VERSION = '0.1.0'
7
+
8
+ def self.perform_backup(config_file)
9
+ return if DreamhostPersonalBackup::StatusManager.is_backup_running?
10
+
11
+ DreamhostPersonalBackup::StatusManager.create_pid_file
12
+
13
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file(config_file)
14
+
15
+ logger = config_parameters[:logger]
16
+
17
+ # Add some newlines for readability
18
+ logger.info("")
19
+ logger.info("")
20
+
21
+ logger.info("Starting new backup run at #{DateTime.now}")
22
+
23
+ config_parameters[:targets].each_value do |target|
24
+ DreamhostPersonalBackup::Backup.run_for_target_directory(target, config_parameters)
25
+ end
26
+
27
+ DreamhostPersonalBackup::StatusManager.remove_pid_file
28
+
29
+ logger.info("Backup run completed at #{DateTime.now}")
30
+ end
31
+
32
+ end
@@ -0,0 +1,36 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require 'dreamhost_personal_backup'
7
+
8
+ task :default => :test
9
+
10
+ desc 'Run all tests'
11
+ task :test => ["test:lib"]
12
+
13
+ namespace :test do
14
+
15
+ desc 'Run gem tests.'
16
+ Rake::TestTask.new(:lib) do |t|
17
+ t.libs << 'lib'
18
+ t.test_files = FileList['test/test*.rb'].exclude('test_helper.rb')
19
+ t.verbose = false
20
+ end
21
+ end
22
+
23
+ begin
24
+ require 'jeweler'
25
+ Jeweler::Tasks.new do |gemspec|
26
+ gemspec.name = "dreamhost-personal-backup"
27
+ gemspec.summary = "Provides functionality to perform personal backups (on Linux or OSX) to a Dreamhost personal backup server."
28
+ gemspec.description = "Provides functionality to perform personal backups (on Linux or OSX) to a Dreamhost personal backup server."
29
+ gemspec.email = "philtrimble@gmail.com"
30
+ gemspec.homepage = "https://github.com/ptrimble/dreamhost-personal-backup"
31
+ gemspec.version = DreamhostPersonalBackup::VERSION
32
+ gemspec.authors = ["Phil Trimble"]
33
+ end
34
+ rescue LoadError
35
+ puts "Jeweler not available. Install it with: gem install jeweler"
36
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ require 'backup/backup'
4
+ require 'logger'
5
+
6
+ class BackupTests < Test::Unit::TestCase
7
+
8
+ CONFIG_PARAMETERS = {:user => "testuser", :host => "localhost", :logger => Logger.new(STDOUT)}
9
+
10
+ SOURCE_DIR_PARAMETER = "/path/to/source"
11
+ DEST_DIR_PARAMETER = "#{CONFIG_PARAMETERS[:user]}@#{CONFIG_PARAMETERS[:host]}:~/"
12
+
13
+ def test_backup_is_performed_without_errors_with_updated_file
14
+ set_expected_rsync_result_as(true)
15
+ assert DreamhostPersonalBackup::Backup.run_for_target_directory(SOURCE_DIR_PARAMETER, CONFIG_PARAMETERS)
16
+ end
17
+
18
+ def test_backup_returns_failure_if_rsync_reports_an_error
19
+ set_expected_rsync_result_as(false)
20
+ assert_equal false, DreamhostPersonalBackup::Backup.run_for_target_directory(SOURCE_DIR_PARAMETER, CONFIG_PARAMETERS)
21
+ end
22
+
23
+ def test_backup_fails_if_user_is_missing
24
+ parameters_with_host_only = {:host => "localhost"}
25
+
26
+ assert_raise(DreamhostPersonalBackup::MissingConfigParameter) {
27
+ DreamhostPersonalBackup::Backup.run_for_target_directory(SOURCE_DIR_PARAMETER, parameters_with_host_only)
28
+ }
29
+ end
30
+
31
+ def test_backup_fails_if_host_is_missing
32
+ parameters_with_user_only = {:user => "testuser"}
33
+
34
+ assert_raise(DreamhostPersonalBackup::MissingConfigParameter) {
35
+ DreamhostPersonalBackup::Backup.run_for_target_directory(SOURCE_DIR_PARAMETER, parameters_with_user_only)
36
+ }
37
+ end
38
+
39
+ private
40
+
41
+ def set_expected_rsync_result_as(rsync_return_code)
42
+ rsync_change = stub(:summary => "timestamp", :filename => "test.dat")
43
+
44
+ rsync_change_array = Array.new
45
+ rsync_change_array.push(rsync_change)
46
+
47
+ rsync_return_code = stub(:success? => rsync_return_code, :changes => rsync_change_array, :error => "rsync example error")
48
+
49
+ suppress_logging_messages
50
+
51
+ Rsync.expects(:run).with(SOURCE_DIR_PARAMETER,
52
+ DEST_DIR_PARAMETER,
53
+ DreamhostPersonalBackup::Backup::RSYNC_COMMAND_ARGS).returns(rsync_return_code)
54
+ end
55
+
56
+ def suppress_logging_messages
57
+ Logger.any_instance.expects(:info).at_least(0).returns(nil)
58
+ Logger.any_instance.expects(:error).at_least(0).returns(nil)
59
+ end
60
+
61
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ require 'backup/configurator'
4
+
5
+ class ConfiguratorTests < Test::Unit::TestCase
6
+
7
+ def test_raise_error_if_config_file_does_not_exist
8
+ assert_raise(DreamhostPersonalBackup::ConfigFileNotFound) {
9
+ DreamhostPersonalBackup::Configurator.process_config_file("/file/does/not/exist")
10
+ }
11
+ end
12
+
13
+ def test_config_file_is_processed_without_errors
14
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_standard_config_file.yml')
15
+ assert config_parameters.is_a?(Hash), "Config parameters should be a hash"
16
+ end
17
+
18
+ def test_config_parameters_set_without_error_from_valid_file
19
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_standard_config_file.yml')
20
+
21
+ assert_equal "testuser", config_parameters[:user]
22
+ assert_equal "testhost.com", config_parameters[:host]
23
+ assert_equal "TestEmail@email.com", config_parameters[:notifyemail]
24
+
25
+ assert config_parameters[:targets].is_a?(Hash)
26
+ end
27
+
28
+ def test_raise_error_if_invalid_parameter_is_passed
29
+ assert_raise(DreamhostPersonalBackup::InvalidConfigParameter) {
30
+ DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_invalid_parameters.yml')
31
+ }
32
+ end
33
+
34
+ def test_all_targets_set_as_expected
35
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_standard_config_file.yml')
36
+
37
+ assert_equal "~/music", config_parameters[:targets]["Music"]
38
+ assert_equal "~/movies", config_parameters[:targets]["Movies"]
39
+ assert_equal "~/photos", config_parameters[:targets]["Photos"]
40
+ end
41
+
42
+ def test_default_log_size_set_if_not_present_in_config_file
43
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_config_file_missing_optional_params.yml')
44
+
45
+ assert_equal DreamhostPersonalBackup::Configurator::DEFAULT_LOG_SIZE, config_parameters[:logrotationsizeinbytes]
46
+ end
47
+
48
+ def test_default_log_file_keep_count_set_if_not_present_in_config_file
49
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_config_file_missing_optional_params.yml')
50
+
51
+ assert_equal DreamhostPersonalBackup::Configurator::DEFAULT_LOG_KEEP_COUNT, config_parameters[:logkeepcount]
52
+ end
53
+
54
+ def test_logger_created_even_if_no_parameters_set
55
+ config_parameters = DreamhostPersonalBackup::Configurator.process_config_file('test/test_files/test_config_file_missing_optional_params.yml')
56
+
57
+ assert_not_nil config_parameters[:logger]
58
+ end
59
+ end
@@ -0,0 +1,5 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ class DreamhostPersonalBackupTests < Test::Unit::TestCase
4
+
5
+ end
@@ -0,0 +1,7 @@
1
+ User: testuser
2
+ Host: testhost.com
3
+
4
+ Targets:
5
+ Music: ~/music
6
+ Movies: ~/movies
7
+ Photos: ~/photos
@@ -0,0 +1,8 @@
1
+ User: testuser
2
+ Host: testhost.com
3
+ LogFile: ~/logs/backup.log
4
+ InvalidParameter: ThisShouldNotBeSet!
5
+ Targets:
6
+ Music: ~/music
7
+ Movies: ~/movies
8
+ Photos: ~/photos
@@ -0,0 +1,11 @@
1
+ User: testuser
2
+ Host: testhost.com
3
+
4
+ NotifyEmail: TestEmail@email.com
5
+
6
+ LogRotationSizeInBytes: 105000000
7
+
8
+ Targets:
9
+ Music: ~/music
10
+ Movies: ~/movies
11
+ Photos: ~/photos
@@ -0,0 +1,20 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ Coveralls::SimpleCov::Formatter,
6
+ SimpleCov::Formatter::HTMLFormatter
7
+ ]
8
+
9
+ SimpleCov.start do
10
+ add_filter 'test'
11
+ end
12
+
13
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '../../lib/'))
14
+
15
+ $KCODE = 'u' if RUBY_VERSION =~ /^1\.8/
16
+
17
+ require 'rubygems'
18
+ require 'test/unit'
19
+
20
+ require 'mocha/setup' # The mocha docs state that this MUST come after the require for test/unit
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/test_helper'
2
+
3
+ require 'backup/status_manager'
4
+
5
+ class StatusManagerTests < Test::Unit::TestCase
6
+
7
+ def test_is_backup_running_returns_false_if_no_pid_file_is_found
8
+ File.expects(:file?).with(File.expand_path(DreamhostPersonalBackup::StatusManager::PID_FILE)).at_least(1).returns(false)
9
+
10
+ assert_equal false, DreamhostPersonalBackup::StatusManager.is_backup_running?
11
+ end
12
+
13
+ def test_is_backup_running_returns_true_if_pid_file_is_found_and_pid_is_running
14
+ File.expects(:file?).with(File.expand_path(DreamhostPersonalBackup::StatusManager::PID_FILE)).at_least(1).returns(true)
15
+
16
+ file_handle = stub(read: "100")
17
+ File.expects(:open).at_least(1).returns(file_handle)
18
+
19
+ Process.expects(:getpgid).at_least(1)
20
+
21
+ assert DreamhostPersonalBackup::StatusManager.is_backup_running?
22
+ end
23
+
24
+ def test_is_backup_running_returns_false_if_pid_file_is_found_and_pid_is_not_running
25
+ File.expects(:file?).with(File.expand_path(DreamhostPersonalBackup::StatusManager::PID_FILE)).at_least(1).returns(true)
26
+
27
+ file_handle = stub(read: "100")
28
+ File.expects(:open).at_least(1).returns(file_handle)
29
+
30
+ Process.expects(:getpgid).at_least(1).raises(Errno::ESRCH)
31
+
32
+ assert_equal false, DreamhostPersonalBackup::StatusManager.is_backup_running?
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dreamhost-personal-backup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Phil Trimble
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rsync
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: simplecov
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: coveralls
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: jeweler
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Provides functionality to perform personal backups (on Linux or OSX)
95
+ to a Dreamhost personal backup server.
96
+ email: philtrimble@gmail.com
97
+ executables:
98
+ - dreamhost_personal_backup
99
+ extensions: []
100
+ extra_rdoc_files:
101
+ - LICENSE
102
+ - README.rdoc
103
+ files:
104
+ - .coveralls.yml
105
+ - .travis.yml
106
+ - CHANGELOG
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE
110
+ - README.rdoc
111
+ - bin/dreamhost_personal_backup
112
+ - dreamhost-personal-backup.gemspec
113
+ - lib/backup/backup.rb
114
+ - lib/backup/configurator.rb
115
+ - lib/backup/status_manager.rb
116
+ - lib/dreamhost_personal_backup.rb
117
+ - rakefile.rb
118
+ - test/test_backup.rb
119
+ - test/test_configurator.rb
120
+ - test/test_dreamhost_personal_backup.rb
121
+ - test/test_files/test_config_file_missing_optional_params.yml
122
+ - test/test_files/test_invalid_parameters.yml
123
+ - test/test_files/test_standard_config_file.yml
124
+ - test/test_helper.rb
125
+ - test/test_status_manager.rb
126
+ homepage: https://github.com/ptrimble/dreamhost-personal-backup
127
+ licenses: []
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubyforge_project:
146
+ rubygems_version: 1.8.23
147
+ signing_key:
148
+ specification_version: 3
149
+ summary: Provides functionality to perform personal backups (on Linux or OSX) to a
150
+ Dreamhost personal backup server.
151
+ test_files: []