akupchanko-astrails-safe 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +3 -0
  3. data/.document +5 -0
  4. data/.gitignore +18 -0
  5. data/.rspec +3 -0
  6. data/CHANGELOG +35 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.markdown +250 -0
  10. data/Rakefile +8 -0
  11. data/TODO +31 -0
  12. data/akupchanko-astrails-safe.gemspec +35 -0
  13. data/bin/astrails-safe +64 -0
  14. data/lib/astrails/safe.rb +68 -0
  15. data/lib/astrails/safe/archive.rb +24 -0
  16. data/lib/astrails/safe/backup.rb +20 -0
  17. data/lib/astrails/safe/cloudfiles.rb +77 -0
  18. data/lib/astrails/safe/config/builder.rb +90 -0
  19. data/lib/astrails/safe/config/node.rb +72 -0
  20. data/lib/astrails/safe/ftp.rb +104 -0
  21. data/lib/astrails/safe/gpg.rb +46 -0
  22. data/lib/astrails/safe/gzip.rb +25 -0
  23. data/lib/astrails/safe/local.rb +51 -0
  24. data/lib/astrails/safe/mongodump.rb +23 -0
  25. data/lib/astrails/safe/mysqldump.rb +32 -0
  26. data/lib/astrails/safe/pgdump.rb +36 -0
  27. data/lib/astrails/safe/pipe.rb +17 -0
  28. data/lib/astrails/safe/s3.rb +80 -0
  29. data/lib/astrails/safe/sftp.rb +88 -0
  30. data/lib/astrails/safe/sink.rb +35 -0
  31. data/lib/astrails/safe/source.rb +47 -0
  32. data/lib/astrails/safe/stream.rb +32 -0
  33. data/lib/astrails/safe/svndump.rb +13 -0
  34. data/lib/astrails/safe/tmp_file.rb +48 -0
  35. data/lib/astrails/safe/version.rb +5 -0
  36. data/lib/extensions/mktmpdir.rb +45 -0
  37. data/spec/astrails/safe/archive_spec.rb +67 -0
  38. data/spec/astrails/safe/cloudfiles_spec.rb +175 -0
  39. data/spec/astrails/safe/config_spec.rb +307 -0
  40. data/spec/astrails/safe/gpg_spec.rb +148 -0
  41. data/spec/astrails/safe/gzip_spec.rb +64 -0
  42. data/spec/astrails/safe/local_spec.rb +109 -0
  43. data/spec/astrails/safe/mongodump_spec.rb +54 -0
  44. data/spec/astrails/safe/mysqldump_spec.rb +83 -0
  45. data/spec/astrails/safe/pgdump_spec.rb +45 -0
  46. data/spec/astrails/safe/s3_spec.rb +168 -0
  47. data/spec/astrails/safe/svndump_spec.rb +39 -0
  48. data/spec/integration/archive_integration_spec.rb +89 -0
  49. data/spec/integration/cleanup_spec.rb +62 -0
  50. data/spec/spec_helper.rb +8 -0
  51. data/templates/script.rb +183 -0
  52. metadata +178 -0
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Astrails::Safe::Pgdump do
4
+
5
+ def def_config
6
+ {
7
+ :options => "OPTS",
8
+ :user => "User",
9
+ :password => "pwd",
10
+ :host => "localhost",
11
+ :port => 7777,
12
+ :skip_tables => [:bar, :baz]
13
+ }
14
+ end
15
+
16
+ def pgdump(id = :foo, config = def_config)
17
+ Astrails::Safe::Pgdump.new(id, Astrails::Safe::Config::Node.new(nil, config))
18
+ end
19
+
20
+ before(:each) do
21
+ stub(Time).now.stub!.strftime {"NOW"}
22
+ end
23
+
24
+ after(:each) { Astrails::Safe::TmpFile.cleanup }
25
+
26
+ describe :backup do
27
+ before(:each) do
28
+ @pg = pgdump
29
+ end
30
+
31
+ {
32
+ :id => "foo",
33
+ :kind => "pgdump",
34
+ :extension => ".sql",
35
+ :filename => "pgdump-foo.NOW",
36
+ :command => "pg_dump OPTS --username='User' --host='localhost' --port='7777' foo",
37
+ }.each do |k, v|
38
+ it "should set #{k} to #{v}" do
39
+ @pg.backup.send(k).should == v
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ describe Astrails::Safe::S3 do
4
+
5
+ def def_config
6
+ {
7
+ :s3 => {
8
+ :bucket => "_bucket",
9
+ :key => "_key",
10
+ :secret => "_secret",
11
+ },
12
+ :keep => {
13
+ :s3 => 2
14
+ }
15
+ }
16
+ end
17
+
18
+ def def_backup(extra = {})
19
+ {
20
+ :kind => "_kind",
21
+ :filename => "/backup/somewhere/_kind-_id.NOW.bar",
22
+ :extension => ".bar",
23
+ :id => "_id",
24
+ :timestamp => "NOW"
25
+ }.merge(extra)
26
+ end
27
+
28
+ def s3(config = def_config, backup = def_backup)
29
+ Astrails::Safe::S3.new(
30
+ Astrails::Safe::Config::Node.new.merge(config),
31
+ Astrails::Safe::Backup.new(backup)
32
+ )
33
+ end
34
+
35
+ describe :cleanup do
36
+
37
+ before(:each) do
38
+ @s3 = s3
39
+
40
+ @files = [4,1,3,2].map { |i| stub(o = {}).key {"aaaaa#{i}"}; o }
41
+
42
+ stub(AWS::S3::Bucket).objects("_bucket", :prefix => "_kind/_id/_kind-_id.", :max_keys => 4) {@files}
43
+ stub(AWS::S3::Bucket).objects("_bucket", :prefix => anything).stub![0].stub!.delete
44
+ end
45
+
46
+ it "should check [:keep, :s3]" do
47
+ @s3.config[:keep].data["s3"] = nil
48
+ dont_allow(@s3.backup).filename
49
+ @s3.send :cleanup
50
+ end
51
+
52
+ it "should delete extra files" do
53
+ mock(AWS::S3::Bucket).objects("_bucket", :prefix => "aaaaa1").mock![0].mock!.delete
54
+ mock(AWS::S3::Bucket).objects("_bucket", :prefix => "aaaaa2").mock![0].mock!.delete
55
+ @s3.send :cleanup
56
+ end
57
+
58
+ end
59
+
60
+ describe :active do
61
+ before(:each) do
62
+ @s3 = s3
63
+ end
64
+
65
+ it "should be true when all params are set" do
66
+ @s3.should be_active
67
+ end
68
+
69
+ it "should be false if bucket is missing" do
70
+ @s3.config[:s3].data["bucket"] = nil
71
+ @s3.should_not be_active
72
+ end
73
+
74
+ it "should be false if key is missing" do
75
+ @s3.config[:s3].data["key"] = nil
76
+ @s3.should_not be_active
77
+ end
78
+
79
+ it "should be false if secret is missing" do
80
+ @s3.config[:s3].data["secret"] = nil
81
+ @s3.should_not be_active
82
+ end
83
+ end
84
+
85
+ describe :path do
86
+ before(:each) do
87
+ @s3 = s3
88
+ end
89
+ it "should use s3/path 1st" do
90
+ @s3.config[:s3].data["path"] = "s3_path"
91
+ @s3.config[:local] = {:path => "local_path"}
92
+ @s3.send(:path).should == "s3_path"
93
+ end
94
+
95
+ it "should use local/path 2nd" do
96
+ @s3.config.merge local: {path: "local_path"}
97
+ @s3.send(:path).should == "local_path"
98
+ end
99
+
100
+ it "should use constant 3rd" do
101
+ @s3.send(:path).should == "_kind/_id"
102
+ end
103
+
104
+ end
105
+
106
+ describe :save do
107
+ def add_stubs(*stubs)
108
+ stubs.each do |s|
109
+ case s
110
+ when :connection
111
+ stub(AWS::S3::Base).establish_connection!(:access_key_id => "_key", :secret_access_key => "_secret", :use_ssl => true)
112
+ when :stat
113
+ stub(File).stat("foo").stub!.size {123}
114
+ when :create_bucket
115
+ stub(AWS::S3::Bucket).find('_bucket') { raise_error AWS::S3::NoSuchBucket }
116
+ stub(AWS::S3::Bucket).create
117
+ when :file_open
118
+ stub(File).open("foo") {|f, block| block.call(:opened_file)}
119
+ when :s3_store
120
+ stub(AWS::S3::S3Object).store(@full_path, :opened_file, "_bucket")
121
+ end
122
+ end
123
+ end
124
+
125
+ before(:each) do
126
+ @s3 = s3(def_config, def_backup(:path => "foo"))
127
+ @full_path = "_kind/_id/backup/somewhere/_kind-_id.NOW.bar.bar"
128
+ end
129
+
130
+ it "should fail if no backup.file is set" do
131
+ @s3.backup.path = nil
132
+ proc {@s3.send(:save)}.should raise_error(RuntimeError)
133
+ end
134
+
135
+ it "should establish s3 connection" do
136
+ mock(AWS::S3::Base).establish_connection!(:access_key_id => "_key", :secret_access_key => "_secret", :use_ssl => true)
137
+ add_stubs(:stat, :create_bucket, :file_open, :s3_store)
138
+ @s3.send(:save)
139
+ end
140
+
141
+ it "should open local file" do
142
+ add_stubs(:connection, :stat, :create_bucket)
143
+ mock(File).open("foo")
144
+ @s3.send(:save)
145
+ end
146
+
147
+ it "should upload file" do
148
+ add_stubs(:connection, :stat, :create_bucket, :file_open)
149
+ mock(AWS::S3::S3Object).store(@full_path, :opened_file, "_bucket")
150
+ @s3.send(:save)
151
+ end
152
+
153
+ it "should fail on files bigger then 5G" do
154
+ add_stubs(:connection)
155
+ mock(File).stat("foo").stub!.size {5*1024*1024*1024+1}
156
+ mock(STDERR).puts(anything)
157
+ dont_allow(Benchmark).realtime
158
+ @s3.send(:save)
159
+ end
160
+
161
+ it 'should not create a bucket that already exists' do
162
+ add_stubs(:connection, :stat, :file_open, :s3_store)
163
+ stub(AWS::S3::Bucket).find('_bucket') { true }
164
+ dont_allow(AWS::S3::Bucket).create
165
+ @s3.send(:save)
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Astrails::Safe::Svndump do
4
+ def def_config
5
+ {
6
+ :options => "OPTS",
7
+ :repo_path => "bar/baz"
8
+ }
9
+ end
10
+
11
+ def svndump(id = :foo, config = def_config)
12
+ Astrails::Safe::Svndump.new(id, Astrails::Safe::Config::Node.new(nil, config))
13
+ end
14
+
15
+ before(:each) do
16
+ stub(Time).now.stub!.strftime {"NOW"}
17
+ end
18
+
19
+ after(:each) { Astrails::Safe::TmpFile.cleanup }
20
+
21
+ describe :backup do
22
+ before(:each) do
23
+ @svn = svndump
24
+ end
25
+
26
+ {
27
+ :id => "foo",
28
+ :kind => "svndump",
29
+ :extension => ".svn",
30
+ :filename => "svndump-foo.NOW",
31
+ :command => "svnadmin dump OPTS bar/baz",
32
+ }.each do |k, v|
33
+ it "should set #{k} to #{v}" do
34
+ @svn.backup.send(k).should == v
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ require "fileutils"
4
+ include FileUtils
5
+
6
+ describe "tar backup" do
7
+ before(:all) do
8
+ # need both local and instance vars
9
+ # instance variables are used in tests
10
+ # local variables are used in the backup definition (instance vars can't be seen)
11
+ @root = root = "tmp/archive_backup_example"
12
+
13
+ # clean state
14
+ rm_rf @root
15
+ mkdir_p @root
16
+
17
+ # create source tree
18
+ @src = src = "#{@root}/src"
19
+ mkdir_p "#{@src}/q/w/e"
20
+ mkdir_p "#{@src}/a/s/d"
21
+
22
+ File.open("#{@src}/qwe1", "w") {|f| f.write("qwe") }
23
+ File.open("#{@src}/q/qwe2", "w") {|f| f.write("qwe"*2) }
24
+ File.open("#{@src}/q/w/qwe3", "w") {|f| f.write("qwe"*3) }
25
+ File.open("#{@src}/q/w/e/qwe4", "w") {|f| f.write("qwe"*4) }
26
+
27
+ File.open("#{@src}/asd1", "w") {|f| f.write("asd") }
28
+ File.open("#{@src}/a/asd2", "w") {|f| f.write("asd" * 2) }
29
+ File.open("#{@src}/a/s/asd3", "w") {|f| f.write("asd" * 3) }
30
+
31
+ @dst = dst = "#{@root}/backup"
32
+ mkdir_p @dst
33
+
34
+ @now = Time.now
35
+ @timestamp = @now.strftime("%y%m%d-%H%M")
36
+
37
+ stub(Time).now {@now} # Freeze
38
+
39
+ config = Astrails::Safe.safe do
40
+ local :path => "#{dst}/:kind"
41
+ tar do
42
+ archive :test1 do
43
+ files src
44
+ exclude "#{src}/q/w"
45
+ exclude "#{src}/q/w/e"
46
+ end
47
+ end
48
+ end
49
+ Astrails::Safe.process config
50
+
51
+ @backup = "#{dst}/archive/archive-test1.#{@timestamp}.tar.gz"
52
+ end
53
+
54
+ it "should create backup file" do
55
+ File.exists?(@backup).should be_true
56
+ end
57
+
58
+ describe "after extracting" do
59
+ before(:all) do
60
+ # prepare target dir
61
+ @target = "#{@root}/test"
62
+ mkdir_p @target
63
+ system "tar -zxvf #{@backup} -C #{@target}"
64
+
65
+ @test = "#{@target}/#{@root}/src"
66
+ puts @test
67
+ end
68
+
69
+ it "should include asd1/2/3" do
70
+ File.exists?("#{@test}/asd1").should be_true
71
+ File.exists?("#{@test}/a/asd2").should be_true
72
+ File.exists?("#{@test}/a/s/asd3").should be_true
73
+ end
74
+
75
+ it "should only include qwe 1 and 2 (no 3)" do
76
+ File.exists?("#{@test}/qwe1").should be_true
77
+ File.exists?("#{@test}/q/qwe2").should be_true
78
+ File.exists?("#{@test}/q/w/qwe3").should be_false
79
+ File.exists?("#{@test}/q/w/e/qwe4").should be_false
80
+ end
81
+
82
+ it "should preserve file content" do
83
+ File.read("#{@test}/qwe1").should == "qwe"
84
+ File.read("#{@test}/q/qwe2").should == "qweqwe"
85
+ File.read("#{@test}/a/s/asd3").should == "asdasdasd"
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ require "fileutils"
4
+ include FileUtils
5
+
6
+ describe "tar backup" do
7
+ before(:all) do
8
+ # need both local and instance vars
9
+ # instance variables are used in tests
10
+ # local variables are used in the backup definition (instance vars can't be seen)
11
+ @root = root = "tmp/cleanup_example"
12
+
13
+ # clean state
14
+ rm_rf @root
15
+ mkdir_p @root
16
+
17
+ # create source tree
18
+ @src = src = "#{@root}/src"
19
+ mkdir_p src
20
+
21
+ File.open(qwe = "#{@src}/qwe", "w") {|f| f.write("qwe") }
22
+
23
+ @dst = dst = "#{@root}/backup"
24
+ mkdir_p "#{@dst}/archive"
25
+
26
+ @now = Time.now
27
+ @timestamp = @now.strftime("%y%m%d-%H%M")
28
+
29
+ stub(Time).now {@now} # Freeze
30
+
31
+ cp qwe, "#{dst}/archive/archive-foo.000001.tar.gz"
32
+ cp qwe, "#{dst}/archive/archive-foo.000002.tar.gz"
33
+ cp qwe, "#{dst}/archive/archive-foobar.000001.tar.gz"
34
+ cp qwe, "#{dst}/archive/archive-foobar.000002.tar.gz"
35
+
36
+ config = Astrails::Safe.safe do
37
+ local :path => "#{dst}/:kind"
38
+ tar do
39
+ keep :local => 1 # only leave the latest
40
+ archive :foo do
41
+ files src
42
+ end
43
+ end
44
+ end
45
+ Astrails::Safe.process config
46
+
47
+ @backup = "#{dst}/archive/archive-foo.#{@timestamp}.tar.gz"
48
+ end
49
+
50
+ it "should create backup file" do
51
+ File.exists?(@backup).should be_true
52
+ end
53
+
54
+ it "should remove old backups" do
55
+ Dir["#{@dst}/archive/archive-foo.*"].should == [@backup]
56
+ end
57
+
58
+ it "should NOT remove backups with base having same prefix" do
59
+ Dir["#{@dst}/archive/archive-foobar.*"].sort.should == ["#{@dst}/archive/archive-foobar.000001.tar.gz", "#{@dst}/archive/archive-foobar.000002.tar.gz"]
60
+ end
61
+
62
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'astrails/safe'
4
+ require 'debugger'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rr
8
+ end
@@ -0,0 +1,183 @@
1
+ safe do
2
+ # same as --verbose on the command line
3
+ # verbose true
4
+
5
+ # same as --local on the command line
6
+ # local_only true
7
+
8
+ # same as --dry-run on the command line
9
+ # dry_run true
10
+
11
+ # backup file path (not including filename)
12
+ # supported substitutions:
13
+ # :kind -> backup 'engine' kind, e.g. "mysqldump" or "archive"
14
+ # :id -> backup 'id', e.g. "blog", "production", etc.
15
+ # :timestamp -> current run timestamp (same for all the backups in the same 'run')
16
+ # you can set separate :path for all backups (or once globally here)
17
+ local do
18
+ path "/backup/:kind"
19
+ end
20
+
21
+ ## uncomment to enable uploads to Amazon S3
22
+ ## Amazon S3 auth (optional)
23
+ # s3 do
24
+ # key YOUR_S3_KEY
25
+ # secret YOUR_S3_SECRET
26
+ # bucket S3_BUCKET
27
+ # # path for uploads to S3. supports same substitution like :local/:path
28
+ # path ":kind/" # this is default
29
+ # end
30
+
31
+ ## alternative style:
32
+ # s3 :key => YOUR_S3_KEY, :secret => YOUR_S3_SECRET, :bucket => S3_BUCKET, :path => ":kind/"
33
+
34
+ ## uncomment to enable uploads to Rackspace Cloud Files
35
+ ## http://www.rackspacecloud.com/cloud_hosting_products/files
36
+ ## Rackspace auth (optional)
37
+ # cloudfiles do
38
+ # user "YOUR_RACKSPACE_CLOUD_USERNAME"
39
+ # api_key "YOUR_RACKSPACE_API_KEY"
40
+ # container "YOUR_CONTAINER_NAME"
41
+ # # path for uploads to Cloud Files, supports same substitution like :local/:path
42
+ # path ":kind/" # this is default
43
+ # # If you are running the backup from a system within the Rackspace/Slicehost network and would like
44
+ # # to back up over the private (unbilled) service net, set this value to true.
45
+ # # service_net true
46
+ # end
47
+
48
+ ## uncomment to enable uploads via SFTP
49
+ # sftp do
50
+ # host "YOUR_REMOTE_HOSTNAME"
51
+ # user "YOUR_REMOTE_USERNAME"
52
+ # # port "NON STANDARD SSH PORT"
53
+ # password "YOUR_REMOTE_PASSWORD"
54
+ # path ":kind/:id" # this is the default
55
+ # end
56
+
57
+ ## uncomment to enable uploads via FTP
58
+ # ftp do
59
+ # host "YOUR_REMOTE_HOSTNAME"
60
+ # user "YOUR_REMOTE_USERNAME"
61
+ # # port "NON STANDARD FTP PORT"
62
+ # password "YOUR_REMOTE_PASSWORD"
63
+ # path ":kind/:id" # this is the default
64
+ # end
65
+
66
+ ## uncomment to enable GPG encryption.
67
+ ## Note: you can use public 'key' or symmetric password but not both!
68
+ # gpg do
69
+ # # you can specify your own gpg executable with the 'command' options
70
+ # # this can be useful for example to choose b/w gpg and gpg2 if both are installed
71
+ # # some gpg installations will automatically set 'use-agent' option in the
72
+ # # config file on the 1st run. see README for more details
73
+ # options "--no-use-agent"
74
+ # # command "/usr/local/bin/gpg"
75
+ # # key "backup@astrails.com"
76
+ # password "astrails"
77
+ # end
78
+
79
+ ## uncomment to enable backup rotation. keep only given number of latest
80
+ ## backups. remove the rest
81
+ # keep do
82
+ # local 4 # keep 4 local backups
83
+ # s3 20 # keep 20 S3 backups
84
+ # end
85
+
86
+ # backup mysql databases with mysqldump
87
+ mysqldump do
88
+ # you can override any setting from parent in a child:
89
+ options "-ceKq --single-transaction --create-options"
90
+
91
+ user "astrails"
92
+ password ""
93
+ # host "localhost"
94
+ # port 3306
95
+ socket "/var/run/mysqld/mysqld.sock"
96
+
97
+ # database is a 'collection' element. it must have a hash or block parameter
98
+ # it will be 'collected' in a 'databases', with database id (1st arg) used as hash key
99
+ # the following code will create mysqldump/databases/blog and mysqldump/databases/mysql configuration 'nodes'
100
+
101
+ # backup database with default values
102
+ # database :blog
103
+
104
+ # backup overriding some values
105
+ # database :production do
106
+ # # you can override 'partially'
107
+ # keep :local => 3
108
+ # # keep/local is 3, and keep/s3 is 20 (from parent)
109
+
110
+ # # local override for gpg password
111
+ # gpg do
112
+ # password "custom-production-pass"
113
+ # end
114
+ # # skip those tables during backup
115
+ # # you can pass an array
116
+ # skip_tables [:logger_exceptions, :request_logs]
117
+ # # or pass them all separately
118
+ # skip_tables :test1
119
+ # skip_tables :test2
120
+ # end
121
+
122
+ end
123
+
124
+ # # uncomment to enable
125
+ # # backup PostgreSQL databases with pg_dump
126
+ # pgdump do
127
+ # options "-i -x -O"
128
+ #
129
+ # user "markmansour"
130
+ # # password "" - leave this out if you have ident setup
131
+ #
132
+ # # database is a 'collection' element. it must have a hash or block parameter
133
+ # # it will be 'collected' in a 'databases', with database id (1st arg) used as hash key
134
+ # database :blog
135
+ # database :production
136
+ # end
137
+
138
+ tar do
139
+ # options "-h" # uncomment this to dereference symbolic links
140
+
141
+ # 'archive' is a collection item, just like 'database'
142
+ # archive "git-repositories" do
143
+ # # files and directories to backup
144
+ # files "/home/git/repositories"
145
+ # # can have more then one 'files' lines or/and use an array
146
+ # files ["/home/dev/work/foo", "/home/dev/work/bar"]
147
+ # end
148
+
149
+ # archive "etc-files" do
150
+ # files "/etc"
151
+ # # exlude those files/directories
152
+ # exclude "/etc/puppet/other"
153
+ # # can have multiple 'exclude' lines or/and use an array
154
+ # exclude ["/etc/tmp/a", "/etc/tmp/b"]
155
+ # end
156
+
157
+ # archive "dot-configs" do
158
+ # files "/home/*/.[^.]*"
159
+ # end
160
+
161
+ # archive "blog" do
162
+ # files "/var/www/blog.astrails.com/"
163
+ # # specify multiple files/directories as array
164
+ # exclude ["/var/www/blog.astrails.com/log", "/var/www/blog.astrails.com/tmp"]
165
+ # end
166
+
167
+ # archive "site" do
168
+ # files "/var/www/astrails.com/"
169
+ # exclude ["/var/www/astrails.com/log", "/var/www/astrails.com/tmp"]
170
+ # end
171
+
172
+ # archive :misc do
173
+ # files [ "/backup/*.rb" ]
174
+ # end
175
+ end
176
+
177
+ # svndump do
178
+ # repo :my_repo do
179
+ # repo_path "/home/svn/my_repo"
180
+ # end
181
+ # end
182
+
183
+ end