astrails-safe 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_helper')
2
+
3
+ describe Astrails::Safe::Gzip do
4
+
5
+ def def_backup
6
+ {
7
+ :compressed => false,
8
+ :command => "command",
9
+ :extension => ".foo",
10
+ :filename => "qweqwe"
11
+ }
12
+ end
13
+
14
+ after(:each) { Astrails::Safe::TmpFile.cleanup }
15
+
16
+ def gzip(config = {}, backup = def_backup)
17
+ Astrails::Safe::Gzip.new(
18
+ @config = Astrails::Safe::Config::Node.new(nil, config),
19
+ @backup = Astrails::Safe::Backup.new(backup)
20
+ )
21
+ end
22
+
23
+ describe :preocess do
24
+
25
+ describe "when not yet compressed" do
26
+ before(:each) { @gzip = gzip }
27
+
28
+ it "should add .gz extension" do
29
+ mock(@backup.extension) << '.gz'
30
+ @gzip.process
31
+ end
32
+
33
+ it "should add |gzip pipe" do
34
+ mock(@backup.command) << '|gzip'
35
+ @gzip.process
36
+ end
37
+
38
+ it "should set compressed" do
39
+ mock(@backup).compressed = true
40
+ @gzip.process
41
+ end
42
+ end
43
+
44
+ describe "when already compressed" do
45
+
46
+ before(:each) { @gzip = gzip({}, :compressed => true) }
47
+
48
+ it "should not touch extension" do
49
+ dont_allow(@backup.extension).<< anything
50
+ @gzip.process
51
+ end
52
+
53
+ it "should not touch command" do
54
+ dont_allow(@backup.command).<< anything
55
+ @gzip.process
56
+ end
57
+
58
+ it "should not touch compressed" do
59
+ dont_allow(@backup).compressed = anything
60
+ @gzip.process
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_helper')
2
+
3
+ describe Astrails::Safe::Local do
4
+ def def_config
5
+ {
6
+ :local => {
7
+ :path => "/:kind~:id~:timestamp"
8
+ }
9
+ }
10
+ end
11
+
12
+ def def_backup
13
+ {
14
+ :kind => "mysqldump",
15
+ :id => "blog",
16
+ :timestamp => "NoW",
17
+ :compressed => true,
18
+ :command => "command",
19
+ :extension => ".foo.gz",
20
+ :filename => "qweqwe"
21
+ }
22
+ end
23
+
24
+ def local(config = def_config, backup = def_backup)
25
+ Astrails::Safe::Local.new(
26
+ @config = Astrails::Safe::Config::Node.new(nil, config),
27
+ @backup = Astrails::Safe::Backup.new(backup)
28
+ )
29
+ end
30
+
31
+ describe :active? do
32
+ it "should be true" do
33
+ local.should be_active
34
+ end
35
+ end
36
+
37
+ describe :prefix do
38
+ it "should raise RuntimeError when no path" do
39
+ lambda {
40
+ local({}).send :prefix
41
+ }.should raise_error(RuntimeError, "missing :local/:path")
42
+ end
43
+
44
+ it "should use local/path" do
45
+ local.send(:prefix).should == "/mysqldump~blog~NoW"
46
+ end
47
+ end
48
+
49
+ describe :save do
50
+ before(:each) do
51
+ @local = local
52
+ stub(@local).system
53
+ stub(@local).path {"file-path"}
54
+ stub(FileUtils).mkdir_p
55
+ end
56
+
57
+ it "should call system to save the file" do
58
+ mock(@local).system("command>file-path")
59
+ @local.send(:save)
60
+ end
61
+
62
+ it "should create directory" do
63
+ mock(FileUtils).mkdir_p("/mysqldump~blog~NoW")
64
+ @local.send(:save)
65
+ end
66
+
67
+ it "should set backup.path" do
68
+ mock(@backup).path = "file-path"
69
+ @local.send(:save)
70
+ end
71
+
72
+ describe "dry run" do
73
+ it "should not create directory"
74
+ it "should not call system"
75
+ it "should set backup.path"
76
+ end
77
+ end
78
+
79
+ describe :cleanup do
80
+ it "should have test"
81
+ end
82
+ end
@@ -0,0 +1,83 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_helper')
2
+
3
+ describe Astrails::Safe::Mysqldump do
4
+
5
+ def def_config
6
+ {
7
+ :options => "OPTS",
8
+ :user => "User",
9
+ :password => "pwd",
10
+ :host => "localhost",
11
+ :port => 7777,
12
+ :socket => "socket",
13
+ :skip_tables => [:bar, :baz]
14
+ }
15
+ end
16
+
17
+ def mysqldump(id = :foo, config = def_config)
18
+ Astrails::Safe::Mysqldump.new(id, Astrails::Safe::Config::Node.new(nil, config))
19
+ end
20
+
21
+ before(:each) do
22
+ stub(Time).now.stub!.strftime {"NOW"}
23
+ end
24
+
25
+ after(:each) { Astrails::Safe::TmpFile.cleanup }
26
+
27
+ describe :backup do
28
+ before(:each) do
29
+ @mysql = mysqldump
30
+ stub(@mysql).mysql_password_file {"/tmp/pwd"}
31
+ end
32
+
33
+ {
34
+ :id => "foo",
35
+ :kind => "mysqldump",
36
+ :extension => ".sql",
37
+ :filename => "mysqldump-foo.NOW",
38
+ :command => "mysqldump --defaults-extra-file=/tmp/pwd OPTS --ignore-table=foo.bar --ignore-table=foo.baz foo",
39
+ }.each do |k, v|
40
+ it "should set #{k} to #{v}" do
41
+ @mysql.backup.send(k).should == v
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ describe :mysql_skip_tables do
48
+ it "should return nil if no skip_tables" do
49
+ config = def_config.dup
50
+ config.delete(:skip_tables)
51
+ m = mysqldump(:foo, Astrails::Safe::Config::Node.new(nil, config))
52
+ stub(m).timestamp {"NOW"}
53
+ m.send(:mysql_skip_tables).should be_nil
54
+ m.backup.command.should_not match(/ignore-table/)
55
+ end
56
+
57
+ it "should return '' if skip_tables empty" do
58
+ config = def_config.dup
59
+ config[:skip_tables] = []
60
+ m = mysqldump(:foo, Astrails::Safe::Config::Node.new(nil, config))
61
+ stub(m).timestamp {"NOW"}
62
+ m.send(:mysql_skip_tables).should == ""
63
+ m.backup.command.should_not match(/ignore-table/)
64
+ end
65
+
66
+ end
67
+
68
+ describe :mysql_password_file do
69
+ it "should create passwords file" do
70
+ m = mysqldump
71
+ file = m.send(:mysql_password_file)
72
+ File.exists?(file).should == true
73
+ File.read(file).should == <<-PWD
74
+ [mysqldump]
75
+ user = User
76
+ password = pwd
77
+ socket = socket
78
+ host = localhost
79
+ port = 7777
80
+ PWD
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_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,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_helper')
2
+
3
+ describe Astrails::Safe::S3 do
4
+
5
+ describe :active do
6
+ it "should be true when all params are set"
7
+ it "should be false if bucket is missing"
8
+ it "should be false if key is missing"
9
+ it "should be false if secret is missing"
10
+ end
11
+
12
+ describe :prefix do
13
+ it "should use s3/path 1st"
14
+ it "should use local/path 2nd"
15
+ it "should use constant 3rd"
16
+ end
17
+
18
+ describe :save do
19
+ it "should establish s3 connection"
20
+ it "should RuntimeError if no local file (i.e. :local didn't run)"
21
+ it "should open local file"
22
+ it "should upload file"
23
+ end
24
+
25
+ describe :cleanup do
26
+ it "should have some tests"
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../example_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
data/lib/astrails/safe.rb CHANGED
@@ -1,4 +1,9 @@
1
+ require "aws/s3"
2
+ require 'fileutils'
3
+
4
+ require 'tempfile'
1
5
  require 'extensions/mktmpdir'
6
+
2
7
  require 'astrails/safe/tmp_file'
3
8
 
4
9
  require 'astrails/safe/config/node'
@@ -6,9 +11,15 @@ require 'astrails/safe/config/builder'
6
11
 
7
12
  require 'astrails/safe/stream'
8
13
 
14
+ require 'astrails/safe/backup'
15
+
16
+ require 'astrails/safe/backup'
17
+
9
18
  require 'astrails/safe/source'
10
19
  require 'astrails/safe/mysqldump'
20
+ require 'astrails/safe/pgdump'
11
21
  require 'astrails/safe/archive'
22
+ require 'astrails/safe/svndump'
12
23
 
13
24
  require 'astrails/safe/pipe'
14
25
  require 'astrails/safe/gpg'
@@ -23,19 +34,25 @@ module Astrails
23
34
  module Safe
24
35
  ROOT = File.join(File.dirname(__FILE__), "..", "..")
25
36
 
26
- def timestamp
27
- @timestamp ||= Time.now.strftime("%y%m%d-%H%M")
28
- end
29
-
30
37
  def safe(&block)
31
38
  config = Config::Node.new(&block)
32
39
  #config.dump
33
40
 
34
- Astrails::Safe::Mysqldump.run(config[:mysqldump, :databases])
35
- Astrails::Safe::Archive.run(config[:tar, :archives])
41
+
42
+ [[Astrails::Safe::Mysqldump, [:mysqldump, :databases]],
43
+ [Astrails::Safe::Pgdump, [:pgdump, :databases]],
44
+ [Astrails::Safe::Archive, [:tar, :archives]],
45
+ [Astrails::Safe::Svndump, [:svndump, :repos]]
46
+ ].each do |klass, path|
47
+ if collection = config[*path]
48
+ collection.each do |name, config|
49
+ klass.new(name, config).backup.run(config, :gpg, :gzip, :local, :s3)
50
+ end
51
+ end
52
+ end
36
53
 
37
54
  Astrails::Safe::TmpFile.cleanup
38
55
  end
56
+ module_function :safe
39
57
  end
40
58
  end
41
-
@@ -16,9 +16,9 @@ module Astrails
16
16
 
17
17
  def tar_files
18
18
  raise RuntimeError, "missing files for tar" unless @config[:files]
19
- [*@config[:files]] * " "
19
+ [*@config[:files]].map {|s| s.strip} * " "
20
20
  end
21
21
 
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Astrails
2
+ module Safe
3
+ class Backup
4
+ attr_accessor :id, :kind, :filename, :extension, :command, :compressed, :timestamp, :path
5
+ def initialize(opts = {})
6
+ opts.each do |k, v|
7
+ self.send("#{k}=", v)
8
+ end
9
+ end
10
+
11
+ def run(config, *mods)
12
+ mods.each do |mod|
13
+ mod = mod.to_s
14
+ mod[0] = mod[0..0].upcase
15
+ Astrails::Safe.const_get(mod).new(config, self).process
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,9 +2,9 @@ module Astrails
2
2
  module Safe
3
3
  module Config
4
4
  class Builder
5
- COLLECTIONS = %w/database archive/
6
- ITEMS = %w/s3 key secret bucket path gpg password keep local mysqldump options
7
- user host port socket skip_tables tar files exclude filename/
5
+ COLLECTIONS = %w/database archive repo/
6
+ ITEMS = %w/s3 key secret bucket path gpg password keep local mysqldump pgdump options
7
+ user host port socket skip_tables tar files exclude filename svndump repo_path/
8
8
  NAMES = COLLECTIONS + ITEMS
9
9
  def initialize(node)
10
10
  @node = node
@@ -27,13 +27,13 @@ module Astrails
27
27
 
28
28
  # do we have data hash?
29
29
  if data = args.shift
30
- die "#{sym}: hash expected: #{data.inspect}" unless data.is_a?(Hash)
30
+ raise "#{sym}: hash expected: #{data.inspect}" unless data.is_a?(Hash)
31
31
  end
32
32
 
33
33
  #puts "#{sym}: args=#{args.inspect}, id_or_value=#{id_or_value}, data=#{data.inspect}, block=#{block.inspect}"
34
34
 
35
- die "#{sym}: unexpected: #{args.inspect}" unless args.empty?
36
- die "#{sym}: missing arguments" unless id_or_value || data || block
35
+ raise "#{sym}: unexpected: #{args.inspect}" unless args.empty?
36
+ raise "#{sym}: missing arguments" unless id_or_value || data || block
37
37
 
38
38
  if COLLECTIONS.include?(sym.to_s) && id_or_value
39
39
  data ||= {}