astrails-safe 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +33 -3
- data/Rakefile +3 -3
- data/VERSION.yml +1 -1
- data/bin/astrails-safe +1 -7
- data/examples/example_helper.rb +3 -3
- data/examples/integration/archive_integration_example.rb +86 -0
- data/examples/unit/archive_example.rb +67 -0
- data/examples/unit/config_example.rb +49 -3
- data/examples/unit/gpg_example.rb +138 -0
- data/examples/unit/gzip_example.rb +64 -0
- data/examples/unit/local_example.rb +82 -0
- data/examples/unit/mysqldump_example.rb +83 -0
- data/examples/unit/pgdump_example.rb +45 -0
- data/examples/unit/s3_example.rb +28 -0
- data/examples/unit/svndump_example.rb +39 -0
- data/lib/astrails/safe.rb +24 -7
- data/lib/astrails/safe/archive.rb +2 -2
- data/lib/astrails/safe/backup.rb +20 -0
- data/lib/astrails/safe/config/builder.rb +6 -6
- data/lib/astrails/safe/config/node.rb +1 -2
- data/lib/astrails/safe/gpg.rb +14 -11
- data/lib/astrails/safe/gzip.rb +8 -8
- data/lib/astrails/safe/local.rb +8 -17
- data/lib/astrails/safe/mysqldump.rb +2 -2
- data/lib/astrails/safe/pgdump.rb +36 -0
- data/lib/astrails/safe/pipe.rb +5 -7
- data/lib/astrails/safe/s3.rb +9 -11
- data/lib/astrails/safe/sink.rb +7 -11
- data/lib/astrails/safe/source.rb +30 -15
- data/lib/astrails/safe/stream.rb +7 -33
- data/lib/astrails/safe/svndump.rb +13 -0
- data/lib/astrails/safe/tmp_file.rb +9 -5
- data/templates/script.rb +13 -0
- metadata +18 -5
- data/examples/unit/stream_example.rb +0 -33
data/lib/astrails/safe/gpg.rb
CHANGED
@@ -2,35 +2,38 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Gpg < Pipe
|
4
4
|
|
5
|
-
def compressed?
|
6
|
-
active? || @parent.compressed?
|
7
|
-
end
|
8
|
-
|
9
5
|
protected
|
10
6
|
|
7
|
+
def post_process
|
8
|
+
@backup.compressed = true
|
9
|
+
end
|
10
|
+
|
11
11
|
def pipe
|
12
12
|
if key
|
13
|
-
|
14
|
-
"|gpg -e -r #{key}"
|
13
|
+
"|gpg #{@config[:options]} -e -r #{key}"
|
15
14
|
elsif password
|
16
|
-
"|gpg -c --passphrase-file #{gpg_password_file(password)}"
|
15
|
+
"|gpg #{@config[:options]} -c --passphrase-file #{gpg_password_file(password)}"
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
19
|
def extension
|
21
|
-
".gpg"
|
20
|
+
".gpg"
|
22
21
|
end
|
23
22
|
|
24
23
|
def active?
|
24
|
+
raise RuntimeError, "can't use both gpg password and pubkey" if key && password
|
25
|
+
|
25
26
|
password || key
|
26
27
|
end
|
27
28
|
|
29
|
+
private
|
30
|
+
|
28
31
|
def password
|
29
|
-
@password ||= config[:gpg, :password]
|
32
|
+
@password ||= @config[:gpg, :password]
|
30
33
|
end
|
31
34
|
|
32
35
|
def key
|
33
|
-
@key ||= config[:gpg, :key]
|
36
|
+
@key ||= @config[:gpg, :key]
|
34
37
|
end
|
35
38
|
|
36
39
|
def gpg_password_file(pass)
|
@@ -39,4 +42,4 @@ module Astrails
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
42
|
-
end
|
45
|
+
end
|
data/lib/astrails/safe/gzip.rb
CHANGED
@@ -2,24 +2,24 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Gzip < Pipe
|
4
4
|
|
5
|
-
def compressed?
|
6
|
-
true
|
7
|
-
end
|
8
|
-
|
9
5
|
protected
|
10
6
|
|
7
|
+
def post_process
|
8
|
+
@backup.compressed = true
|
9
|
+
end
|
10
|
+
|
11
11
|
def pipe
|
12
|
-
"|gzip"
|
12
|
+
"|gzip"
|
13
13
|
end
|
14
14
|
|
15
15
|
def extension
|
16
|
-
".gz"
|
16
|
+
".gz"
|
17
17
|
end
|
18
18
|
|
19
19
|
def active?
|
20
|
-
!@
|
20
|
+
!@backup.compressed
|
21
21
|
end
|
22
22
|
|
23
23
|
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
data/lib/astrails/safe/local.rb
CHANGED
@@ -2,45 +2,37 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Local < Sink
|
4
4
|
|
5
|
-
def open(&block)
|
6
|
-
return @parent.open(&block) unless active?
|
7
|
-
run
|
8
|
-
File.open(path, &block) unless $DRY_RUN
|
9
|
-
end
|
10
|
-
|
11
5
|
protected
|
12
6
|
|
13
7
|
def active?
|
14
8
|
# S3 can't upload from pipe. it needs to know file size, so we must pass through :local
|
15
|
-
# will change once we add SSH sink
|
9
|
+
# will change once we add SSH/FTP sink
|
16
10
|
true
|
17
11
|
end
|
18
12
|
|
19
13
|
def prefix
|
20
|
-
@prefix ||= File.expand_path(expand(@config[:local, :path] || raise(RuntimeError, "missing :local/:path
|
21
|
-
end
|
22
|
-
|
23
|
-
def command
|
24
|
-
"#{@parent.command} > #{path}"
|
14
|
+
@prefix ||= File.expand_path(expand(@config[:local, :path] || raise(RuntimeError, "missing :local/:path")))
|
25
15
|
end
|
26
16
|
|
27
17
|
def save
|
28
|
-
puts "command: #{command}" if $_VERBOSE
|
18
|
+
puts "command: #{@backup.command}" if $_VERBOSE
|
19
|
+
|
29
20
|
unless $DRY_RUN
|
30
21
|
FileUtils.mkdir_p(prefix) unless File.directory?(prefix)
|
31
|
-
system command
|
22
|
+
system "#{@backup.command}>#{@backup.path = path}"
|
32
23
|
end
|
24
|
+
|
33
25
|
end
|
34
26
|
|
35
27
|
def cleanup
|
36
28
|
return unless keep = @config[:keep, :local]
|
37
29
|
|
38
|
-
base = File.basename(filename).split(".").first
|
30
|
+
base = File.basename(@backup.filename).split(".").first
|
39
31
|
|
40
32
|
pattern = File.join(prefix, "#{base}*")
|
41
33
|
puts "listing files #{pattern.inspect}" if $_VERBOSE
|
42
34
|
files = Dir[pattern] .
|
43
|
-
select{|f| File.file?(f)} .
|
35
|
+
select{|f| File.file?(f) && File.size(f) > 0} .
|
44
36
|
sort
|
45
37
|
|
46
38
|
cleanup_with_limit(files, keep) do |f|
|
@@ -48,7 +40,6 @@ module Astrails
|
|
48
40
|
File.unlink(f) unless $DRY_RUN
|
49
41
|
end
|
50
42
|
end
|
51
|
-
|
52
43
|
end
|
53
44
|
end
|
54
45
|
end
|
@@ -3,7 +3,7 @@ module Astrails
|
|
3
3
|
class Mysqldump < Source
|
4
4
|
|
5
5
|
def command
|
6
|
-
|
6
|
+
"mysqldump --defaults-extra-file=#{mysql_password_file} #{@config[:options]} #{mysql_skip_tables} #{@id}"
|
7
7
|
end
|
8
8
|
|
9
9
|
def extension; '.sql'; end
|
@@ -28,4 +28,4 @@ module Astrails
|
|
28
28
|
|
29
29
|
end
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Astrails
|
2
|
+
module Safe
|
3
|
+
class Pgdump < Source
|
4
|
+
|
5
|
+
def command
|
6
|
+
if @config["password"]
|
7
|
+
ENV['PGPASSWORD'] = @config["password"]
|
8
|
+
else
|
9
|
+
ENV['PGPASSWORD'] = nil
|
10
|
+
end
|
11
|
+
"pg_dump #{postgres_options} #{postgres_username} #{postgres_host} #{postgres_port} #{@id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def extension; '.sql'; end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def postgres_options
|
19
|
+
@config[:options]
|
20
|
+
end
|
21
|
+
|
22
|
+
def postgres_host
|
23
|
+
@config["host"] && "--host='#{@config["host"]}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
def postgres_port
|
27
|
+
@config["port"] && "--port='#{@config["port"]}'"
|
28
|
+
end
|
29
|
+
|
30
|
+
def postgres_username
|
31
|
+
@config["user"] && "--username='#{@config["user"]}'"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/astrails/safe/pipe.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
module Astrails
|
2
2
|
module Safe
|
3
3
|
class Pipe < Stream
|
4
|
+
def process
|
5
|
+
return unless active?
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
+
@backup.command << pipe
|
8
|
+
@backup.extension << extension
|
9
|
+
post_process
|
7
10
|
end
|
8
|
-
|
9
|
-
def filename
|
10
|
-
"#{@parent.filename}#{extension}"
|
11
|
-
end
|
12
|
-
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
data/lib/astrails/safe/s3.rb
CHANGED
@@ -9,32 +9,30 @@ module Astrails
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def prefix
|
12
|
-
@prefix ||= expand(config[:s3, :path] ||
|
12
|
+
@prefix ||= expand(config[:s3, :path] || config[:local, :path] || ":kind/:id")
|
13
13
|
end
|
14
14
|
|
15
15
|
def save
|
16
|
+
raise RuntimeError, "pipe-streaming not supported for S3." unless @backup.path
|
17
|
+
|
16
18
|
# needed in cleanup even on dry run
|
17
19
|
AWS::S3::Base.establish_connection!(:access_key_id => key, :secret_access_key => secret, :use_ssl => true) unless $LOCAL
|
18
20
|
|
19
|
-
file = @parent.open
|
20
21
|
puts "Uploading #{bucket}:#{path}" if $_VERBOSE || $DRY_RUN
|
21
22
|
unless $DRY_RUN || $LOCAL
|
22
23
|
AWS::S3::Bucket.create(bucket)
|
23
|
-
|
24
|
+
File.open(@backup.path) do |file|
|
25
|
+
AWS::S3::S3Object.store(path, file, bucket)
|
26
|
+
end
|
24
27
|
puts "...done" if $_VERBOSE
|
25
28
|
end
|
26
|
-
file.close if file
|
27
|
-
|
28
29
|
end
|
29
30
|
|
30
31
|
def cleanup
|
31
|
-
|
32
32
|
return if $LOCAL
|
33
33
|
|
34
34
|
return unless keep = @config[:keep, :s3]
|
35
35
|
|
36
|
-
bucket = @config[:s3, :bucket]
|
37
|
-
|
38
36
|
base = File.basename(filename).split(".").first
|
39
37
|
|
40
38
|
puts "listing files in #{bucket}:#{prefix}/#{base}"
|
@@ -52,15 +50,15 @@ module Astrails
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def bucket
|
55
|
-
config[:s3, :bucket]
|
53
|
+
@config[:s3, :bucket]
|
56
54
|
end
|
57
55
|
|
58
56
|
def key
|
59
|
-
config[:s3, :key]
|
57
|
+
@config[:s3, :key]
|
60
58
|
end
|
61
59
|
|
62
60
|
def secret
|
63
|
-
config[:s3, :secret]
|
61
|
+
@config[:s3, :secret]
|
64
62
|
end
|
65
63
|
|
66
64
|
end
|
data/lib/astrails/safe/sink.rb
CHANGED
@@ -2,20 +2,18 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Sink < Stream
|
4
4
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@parent.run
|
11
|
-
end
|
5
|
+
def process
|
6
|
+
return unless active?
|
7
|
+
|
8
|
+
save
|
9
|
+
cleanup
|
12
10
|
end
|
13
11
|
|
14
12
|
protected
|
15
13
|
|
16
14
|
# prefix is defined in subclass
|
17
15
|
def path
|
18
|
-
@path ||= File.join(prefix, filename)
|
16
|
+
@path ||= File.join(prefix, @backup.filename) + @backup.extension
|
19
17
|
end
|
20
18
|
|
21
19
|
# call block on files to be removed (all except for the LAST 'limit' files
|
@@ -26,8 +24,6 @@ module Astrails
|
|
26
24
|
# TODO: validate here
|
27
25
|
to_remove.each(&block)
|
28
26
|
end
|
29
|
-
|
30
27
|
end
|
31
28
|
end
|
32
|
-
end
|
33
|
-
|
29
|
+
end
|
data/lib/astrails/safe/source.rb
CHANGED
@@ -2,27 +2,42 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Source < Stream
|
4
4
|
|
5
|
+
attr_accessor :id
|
5
6
|
def initialize(id, config)
|
6
|
-
@id, @config = id, config
|
7
|
+
@id, @config = id.to_s, config
|
8
|
+
end
|
9
|
+
|
10
|
+
def timestamp
|
11
|
+
Time.now.strftime("%y%m%d-%H%M")
|
12
|
+
end
|
13
|
+
|
14
|
+
def kind
|
15
|
+
self.class.human_name
|
7
16
|
end
|
8
17
|
|
9
18
|
def filename
|
10
|
-
@filename ||= expand(":kind-:id.:timestamp
|
19
|
+
@filename ||= expand(":kind-:id.:timestamp")
|
11
20
|
end
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def backup
|
23
|
+
return @backup if @backup
|
24
|
+
@backup = Backup.new(
|
25
|
+
:id => @id,
|
26
|
+
:kind => kind,
|
27
|
+
:extension => extension,
|
28
|
+
:command => command,
|
29
|
+
:timestamp => timestamp
|
30
|
+
)
|
31
|
+
# can't do this in the initializer hash above since
|
32
|
+
# filename() calls expand() which requires @backup
|
33
|
+
@backup.filename = filename
|
34
|
+
@backup
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def self.human_name
|
40
|
+
name.split('::').last.downcase
|
26
41
|
end
|
27
42
|
|
28
43
|
end
|
data/lib/astrails/safe/stream.rb
CHANGED
@@ -2,44 +2,18 @@ module Astrails
|
|
2
2
|
module Safe
|
3
3
|
class Stream
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def id
|
10
|
-
@id ||= @parent.id
|
11
|
-
end
|
12
|
-
|
13
|
-
def config
|
14
|
-
@config ||= @parent.config
|
15
|
-
end
|
16
|
-
|
17
|
-
def filename
|
18
|
-
@parent.filename
|
19
|
-
end
|
20
|
-
|
21
|
-
def compressed?
|
22
|
-
@parent && @parent.compressed?
|
23
|
-
end
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
|
-
def self.human_name
|
28
|
-
name.split('::').last.downcase
|
29
|
-
end
|
30
|
-
|
31
|
-
def kind
|
32
|
-
@parent ? @parent.kind : self.class.human_name
|
5
|
+
attr_accessor :config, :backup
|
6
|
+
def initialize(config, backup)
|
7
|
+
@config, @backup = config, backup
|
33
8
|
end
|
34
9
|
|
35
10
|
def expand(path)
|
36
11
|
path .
|
37
|
-
|
38
|
-
|
39
|
-
|
12
|
+
gsub(/:kind\b/, @backup.kind.to_s) .
|
13
|
+
gsub(/:id\b/, @backup.id.to_s) .
|
14
|
+
gsub(/:timestamp\b/, @backup.timestamp)
|
40
15
|
end
|
41
16
|
|
42
17
|
end
|
43
18
|
end
|
44
|
-
end
|
45
|
-
|
19
|
+
end
|