diff --git a/.travis.yml b/.travis.yml
index 240935c..6146b06 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,14 +7,10 @@ sudo: false
matrix:
fast_finish: true
include:
- - rvm: 1.8.7
- env: PUPPET_GEM_VERSION="~> 3.3.0"
- - rvm: 1.8.7
- env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
- rvm: 1.9.3
- env: PUPPET_GEM_VERSION="~> 3.3.0"
+ env: PUPPET_GEM_VERSION="~> 3.8.0" JSON_PURE_GEM_VERSION="~> 1.8.3"
- rvm: 1.9.3
- env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
+ env: PUPPET_GEM_VERSION="~> 3.0" JSON_PURE_GEM_VERSION="~> 1.8.3" FUTURE_PARSER="yes"
- rvm: 2.0.0
env: PUPPET_GEM_VERSION="~> 3.3.0"
- rvm: 2.0.0
@@ -25,13 +21,3 @@ matrix:
env: PUPPET_GEM_VERSION="~> 4.1"
- rvm: 2.1.0
env: PUPPET_GEM_VERSION="~> 4.2"
-notifications:
- email: false
- hipchat:
- rooms:
- - secure: CK11caPkzorkB4onwQPDolAFM32RO+Mn/rt3MRBe0xkt+SyRj8Icmv4MLbWUhiIydZQLrZpC+k993U9RuNOgghOcBq9tKF3U1sM6rrWLNJOnvobi6S+WZYe325IcsMchREERd0TUJYeYWCw2YxYlJBS/xRmpXO5gLZAPzm1NI9k=
- template:
- - '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (Details/Change view)'
- format: html
- on_success: always
- on_failure: always
diff --git a/Gemfile b/Gemfile
index 007789b..3426dae 100644
--- a/Gemfile
+++ b/Gemfile
@@ -9,6 +9,11 @@ group :unit_tests do
gem 'puppet-syntax', :require => false
gem 'metadata-json-lint', :require => false
gem 'json', :require => false
+ if jasonpureversion = ENV['JSON_PURE_GEM_VERSION']
+ gem 'json_pure', jasonpureversion, :require => false
+ else
+ gem 'json_pure', :require => false
+ end
gem 'puppet-lint-absolute_classname-check', :require => false
gem 'puppet-lint-appends-check', :require => false
gem 'puppet-lint-empty_string-check', :require => false
diff --git a/README.md b/README.md
index d2d4581..29fce2d 100644
--- a/README.md
+++ b/README.md
@@ -276,6 +276,22 @@ String. Bucket to store archive when using S3 storage type
String. Region to store archive when using S3 storage type
+##### `rsync_mode`
+
+String. rsync mode to use with rsync storage
+
+##### `rsync_port`
+
+Integer. Port for rsync storage model to use
+
+Default: 22
+
+##### `rsync_compress`
+
+Boolean. Weather or not to enable rsync compression on transfer
+
+Default: undef (false)
+
##### `encryptor`
String. Encryptor to use on backup archive
diff --git a/manifests/init.pp b/manifests/init.pp
index 239f96f..6d90888 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -37,6 +37,9 @@
# FTP
$ftp_port = $::backup::params::ftp_port,
$ftp_passive_mode = $::backup::params::ftp_passive_mode,
+ # Rsync
+ $rsync_mode = $::backup::params::rsync_mode,
+ $rsync_password_file = $::backup::params::rsync_password_file,
## Encryptors
$encryptor = $::backup::params::encryptor,
diff --git a/manifests/job.pp b/manifests/job.pp
index d103c8a..a7449f0 100644
--- a/manifests/job.pp
+++ b/manifests/job.pp
@@ -58,6 +58,11 @@
# FTP
$ftp_port = $::backup::ftp_port,
$ftp_passive_mode = $::backup::ftp_passive_mode,
+ # rsync
+ $rsync_mode = $::backup::rsync_mode,
+ $rsync_port = $::backup::rsync_port,
+ $rsync_compress = $::backup::rsync_compress,
+ $rsync_password_file = $::backup::rsync_password_file,
## Encryptors
$encryptor = $::backup::encryptor,
@@ -173,8 +178,8 @@
}
# Storage
- if !member(['s3', 'local', 'ftp'], $storage_type) {
- fail("[Backup::Job::${name}]: Currently supported storage types are: ftp, local, and s3")
+ if !member(['s3', 'local', 'ftp', 'rsync'], $storage_type) {
+ fail("[Backup::Job::${name}]: Currently supported storage types are: ftp, local, s3, and rsync")
}
if $keep and !is_integer($keep) {
@@ -186,7 +191,7 @@
}
# local and ftp require path parameter
- if member(['ftp', 'local'], $storage_type) {
+ if member(['ftp', 'local', 'rsync'], $storage_type) {
if !$path {
fail("[Backup::Job::${name}]: Path parameter is required with storage_type => ${storage_type}")
}
@@ -243,6 +248,30 @@
validate_bool($ftp_passive_mode)
}
+ if $storage_type == 'rsync' {
+ if $rsync_mode and !member([
+ 'ssh',
+ 'ssh_daemon',
+ 'rsync_daemon',
+ ], $rsync_mode ) {
+ fail("[Backup::Job::${name}]: ${rsync_mode} is not a valid mode")
+ }
+ if !$storage_host or !is_string($storage_host) {
+ fail("[Backup::Job::${name}]: Parameter storage_host is required for rsync storage")
+ }
+ if $rsync_port and !is_integer($rsync_port) {
+ fail("[Backup::Job::${name}]: rsync_port must be an integer. (Got: ${rsync_port})")
+ }
+
+ if $rsync_compress {
+ validate_bool($rsync_compress)
+ }
+ if $rsync_password_file {
+ validate_string($rsync_password_file)
+ }
+
+ }
+
# Encryptor
if $encryptor and !member(['openssl'], $encryptor) {
fail("[Backup::Job::${name}]: Supported encryptors are openssl")
@@ -479,6 +508,19 @@
content => template('backup/job/ftp.erb'),
order => '35',
}
+ } elsif $storage_type == 'rsync' {
+ # Template uses
+ # - $server_username
+ # - $server_ip
+ # - $server_port
+ # - $server_compress
+ # - $server_mode
+ # - $path
+ concat::fragment { "${_name}_rsync":
+ target => "/etc/backup/models/${_name}.rb",
+ content => template('backup/job/rsync.erb'),
+ order => '35',
+ }
}
if $logfile_enabled or $syslog_enabled or $console_quiet {
diff --git a/manifests/params.pp b/manifests/params.pp
index c2d6761..28dfeb9 100644
--- a/manifests/params.pp
+++ b/manifests/params.pp
@@ -53,6 +53,11 @@
# FTP
$ftp_port = 21
$ftp_passive_mode = false
+ # rsync
+ $rsync_mode = undef
+ $rsync_port = undef
+ $rsync_compress = undef
+ $rsync_password_file = undef
## Encryptors
$encryptor = undef
diff --git a/spec/defines/backup_job_spec.rb b/spec/defines/backup_job_spec.rb
index c518928..0806d22 100644
--- a/spec/defines/backup_job_spec.rb
+++ b/spec/defines/backup_job_spec.rb
@@ -346,6 +346,97 @@
end
end # ftp
+ context 'rsync' do
+ context 'bad mode' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ :rsync_mode => 'abcde'
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/abcde is not a valid mode/)}
+ end
+
+ context 'missing host' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :path => '/there',
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/storage_host is required/)}
+ end
+
+ context 'missing path' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/Path parameter is required/)}
+ end
+
+ context 'bad port' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ :rsync_port => 'abcde',
+ :path => '/there',
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/rsync_port must be an integer/)}
+ end
+
+ context 'bad rsync_compress' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ :rsync_compress => 'bob',
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/"bob" is not a boolean/)}
+ end
+
+ context 'bad rsync_compress' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ :rsync_compress => 'bob',
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/"bob" is not a boolean/)}
+ end
+
+ context 'rsync_password_file is not a string' do
+ let(:params) { {
+ :types => 'archive',
+ :add => 'here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ :rsync_compress => true,
+ :rsync_mode => 'rsync_daemon',
+ :rsync_password_file => true
+ } }
+ it { expect { is_expected.to compile }.to raise_error(/true is not a string/)}
+ end
+
+ end # rsync
+
context 'encryptor generic' do
context 'bad encryptor' do
let(:params) { {
@@ -1014,6 +1105,54 @@
end
end # ftp
+ context 'rsync' do
+ context 'minimum settings' do
+ let(:params) { {
+ :types => 'archive',
+ :add => '/here',
+ :storage_type => 'rsync',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ } }
+ it { should_not contain_concat__fragment('job1_rsync').with(:content => /server\..+user/) }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.host\s+=\s"mysite.example.com"/) }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.path\s+=\s"\/there"/) }
+ it { should_not contain_concat__fragment('job1_rsync').with(:content => /server\.rsync_compress/) }
+ end
+
+ context 'all params' do
+ let(:params) { {
+ :types => 'archive',
+ :add => '/here',
+ :storage_type => 'rsync',
+ :storage_username => 'myuser',
+ :storage_host => 'mysite.example.com',
+ :path => '/there',
+ :rsync_port => 22,
+ :rsync_mode => 'ssh',
+ :keep => 10,
+ } }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\..+user\s+=\s"myuser"/) }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.port\s+=\s22/) }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.mode\s+=\s:ssh/) }
+ end
+
+ context 'rsync_daemon mode' do
+ let(:params) { {
+ :types => 'archive',
+ :add => '/here',
+ :storage_type => 'rsync',
+ :storage_host => 'mysite.example.com',
+ :path => 'there',
+ :rsync_port => 873,
+ :rsync_mode => 'rsync_daemon',
+ :keep => 10,
+ } }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.port\s+=\s873/) }
+ it { should contain_concat__fragment('job1_rsync').with(:content => /server\.mode\s+=\s:rsync_daemon/) }
+ end
+ end # rsync
+
context 'logging' do
context 'no logging' do
let(:params) { {
diff --git a/templates/job/rsync.erb b/templates/job/rsync.erb
new file mode 100644
index 0000000..1a8a099
--- /dev/null
+++ b/templates/job/rsync.erb
@@ -0,0 +1,24 @@
+ ##
+ # rsync [Storage]
+ #
+ store_with RSync do |server|
+<%if @storage_username and (@rsync_mode == 'ssh') -%>
+ server.ssh_user = "<%= @storage_username -%>"
+<% elsif @storage_username -%>
+ server.rsync_user = "<%= @storage_username -%>"
+<% end -%>
+ server.host = "<%= @storage_host -%>"
+<%if @rsync_port -%>
+ server.port = <%= @rsync_port %>
+<% end -%>
+ server.path = "<%= @_path -%>"
+<% if @rsync_compress -%>
+ server.compress = "<%= @rsync_compress %>"
+<% end -%>
+<% if @rsync_mode -%>
+ server.mode = :<%= @rsync_mode %>
+<% end -%>
+<% if @rsync_password_file -%>
+ server.rsync_password_file = "<%= @rsync_password_file %>"
+<% end -%>
+ end