blanket 0.0.1

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.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Jim Van Fleet <jim@jimvanfleet.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,3 @@
1
+ Welcome to Blanket!
2
+
3
+ https://github.com/bigfleet/blanket/wikis is the canonical online source for info on Blanket.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'capistrano/cli'
3
+ dir = ARGV.shift
4
+ ARGV << "sink:export"
5
+ FileUtils.cd(dir)
6
+ Capistrano::CLI.execute
7
+
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'fileutils'
4
+
5
+ require 'blanket/init'
6
+
7
+ # default options
8
+ OPTIONS = {
9
+ }
10
+
11
+
12
+ ARGV.options do |o|
13
+ script_name = File.basename($0)
14
+
15
+ o.set_summary_indent(' ')
16
+ o.banner = "Usage: #{script_name} [OPTIONS]"
17
+ o.define_head "Configure blanket task with source and sink information"
18
+ o.separator ""
19
+
20
+ o.on("-t", "--task=val", String,
21
+ "name of the task") { |OPTIONS[:task]| }
22
+ o.on("-o", "--source=val", String,
23
+ "blanket type of the source") { |OPTIONS[:source]| }
24
+ o.on("-i", "--sink=val", String,
25
+ "blanket type of the sink") { |OPTIONS[:sink]| }
26
+
27
+ o.separator ""
28
+
29
+ o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
30
+
31
+ o.parse!
32
+ end
33
+
34
+ BAD_ARGS = "You failed to supply all the required arguments. Please use -h and try again.\n"
35
+ $stderr << BAD_ARGS unless OPTIONS[:task] && OPTIONS[:source] && OPTIONS[:sink]
36
+
37
+ task = OPTIONS[:task]
38
+ source_class = OPTIONS[:source]
39
+ @task_dir = FileUtils.pwd + "/" +task
40
+ puts "Creating #{@task_dir}"
41
+ FileUtils.mkdir_p @task_dir
42
+
43
+ def write_config_for(sym)
44
+ file = @task_dir + "/#{sym.to_s}.yml"
45
+ atts = Object.const_get(OPTIONS[sym]).default_attributes
46
+ writer = Blanket::Writer.new(atts)
47
+ puts "Writing #{sym} configuration #{file}"
48
+ writer.write(file)
49
+ end
50
+
51
+ write_config_for(:source)
52
+ write_config_for(:sink)
53
+
54
+
55
+ def unindent(string)
56
+ indentation = string[/\A\s*/]
57
+ string.strip.gsub(/^#{indentation}/, "")
58
+ end
59
+
60
+ files = {
61
+ "Capfile" => unindent(<<-FILE),
62
+ require 'capistrano/recipes/blanket'
63
+ FILE
64
+ }
65
+
66
+ files.each do |file, content|
67
+ file = File.join(@task_dir, file)
68
+ if File.exists?(file)
69
+ warn "[skip] `#{file}' already exists"
70
+ elsif File.exists?(file.downcase)
71
+ warn "[skip] `#{file.downcase}' exists, which could conflict with `#{file}'"
72
+ elsif !File.exists?(File.dirname(file))
73
+ warn "[skip] directory `#{File.dirname(file)}' does not exist"
74
+ else
75
+ puts "[add] writing `#{file}'"
76
+ File.open(file, "w") { |f| f.write(content) }
77
+ end
78
+ end
79
+
80
+ puts "[done] blanketed!"
@@ -0,0 +1,31 @@
1
+ module Blanket
2
+ class Reader
3
+
4
+ def initialize(path)
5
+ @path = path
6
+ @attributes = YAML.load_file(@path)
7
+ end
8
+
9
+ def method_missing(symbol)
10
+ @attributes[symbol.to_s]
11
+ rescue
12
+ nil
13
+ end
14
+
15
+ def keys
16
+ blanket_type.attribute_symbols
17
+ end
18
+
19
+ def self.blanketize(path)
20
+ reader = Reader.new(path)
21
+ blanket_type.new(@attributes)
22
+ end
23
+
24
+ private
25
+
26
+ def blanket_type
27
+ btype = @attributes["source_type"] || @attributes["sink_type"]
28
+ Object.const_get(btype)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ module Blanket
2
+ class Writer
3
+ def initialize(attributes)
4
+ @attributes = attributes
5
+ end
6
+
7
+ def write(path)
8
+ File.delete(path) if File.exist?(path)
9
+ write_to = File.new(path, File::CREAT, 0644)
10
+ File.open(path, "w") do |out|
11
+ YAML.dump(@attributes, out)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ gem 'aws-s3'
4
+ gem 'rake'
5
+ gem 'capistrano'
6
+ require 'rake'
7
+ require 'capistrano'
8
+ require 'aws/s3'
9
+ require 'pathname'
10
+
11
+ # God, this is laborious. I need to know how to do this better.
12
+
13
+ require File.dirname(__FILE__) + "/utils.rb"
14
+ require File.dirname(__FILE__) + "/config/reader.rb"
15
+ require File.dirname(__FILE__) + "/config/writer.rb"
16
+ require File.dirname(__FILE__) + "/sink.rb"
17
+ require File.dirname(__FILE__) + "/source.rb"
18
+ require File.dirname(__FILE__) + "/plugins/sources/confluence.rb"
19
+ require File.dirname(__FILE__) + "/plugins/sources/mysql.rb"
20
+ require File.dirname(__FILE__) + "/plugins/sources/subversion.rb"
21
+ require File.dirname(__FILE__) + "/plugins/sinks/s3.rb"
@@ -0,0 +1,67 @@
1
+ gem 'aws-s3'
2
+ class S3 < Sink
3
+
4
+ include AWS::S3
5
+
6
+ attr_accessor :reader
7
+
8
+ def initialize(reader)
9
+ @reader = reader
10
+ end
11
+
12
+ def self.attribute_symbols
13
+ [:access_key_id, :secret_access_key, :sink_type, :bucket]
14
+ end
15
+
16
+ def self.default_sink_type
17
+ "S3"
18
+ end
19
+
20
+ def self.default_access_key_id
21
+ "your-id"
22
+ end
23
+
24
+ def self.default_secret_access_key
25
+ "your-secret-ket"
26
+ end
27
+
28
+ def self.default_bucket
29
+ "s3-bucket"
30
+ end
31
+
32
+ def find_bucket(bucket)
33
+ begin
34
+ Bucket.find(bucket)
35
+ rescue NoSuchBucket
36
+ S3.create_bucket(bucket)
37
+ find_bucket(bucket)
38
+ end
39
+ end
40
+
41
+ def self.create_bucket(name)
42
+ Bucket.create(name)
43
+ end
44
+
45
+ def open_connection
46
+ AWS::S3::Base.establish_connection!(
47
+ :access_key_id => @reader.access_key_id,
48
+ :secret_access_key => @reader.secret_access_key
49
+ )
50
+ end
51
+
52
+ def log(msg, lvl)
53
+ puts msg
54
+ end
55
+
56
+ def drain(bucket, backup_file)
57
+ open_connection
58
+ s3_bucket = find_bucket(bucket)
59
+ if s3_bucket[backup_file]
60
+ log("Removing existing #{backup_file}", :info)
61
+ S3Object.delete(backup_file.to_s, bucket)
62
+ end
63
+ log("Uploading #{backup_file} to S3", :info)
64
+ S3Object.store(backup_file.to_s, File.open(backup_file), bucket)
65
+ end
66
+
67
+ end
@@ -0,0 +1,60 @@
1
+ require 'date'
2
+ class Confluence < Source
3
+
4
+ def initialize(reader)
5
+ @reader = reader
6
+ end
7
+
8
+ def self.attribute_symbols
9
+ [:source_type, :host, :user, :password, :remote_directory, :local_directory ]
10
+ end
11
+
12
+ def self.default_source_type
13
+ "Confluence"
14
+ end
15
+
16
+ def self.default_host
17
+ "yourhost.com"
18
+ end
19
+
20
+ def self.default_user
21
+ "username"
22
+ end
23
+
24
+ def self.default_password
25
+ "password"
26
+ end
27
+
28
+ def self.default_remote_directory
29
+ "/path/to/remote/confluence/backups"
30
+ end
31
+
32
+ def self.default_local_directory
33
+ "/path/to/local/confluence/backups"
34
+ end
35
+
36
+
37
+ def self.filename
38
+ #On my system, they're named daily-backup-2008_02_24.zip
39
+ today = Date.today
40
+ "daily-backup-#{today.strftime("%Y_%m_%d")}.zip"
41
+ end
42
+
43
+ def remote_backup_path
44
+ [remote_directory, Confluence.filename].join('/')
45
+ end
46
+
47
+ def local_backup_path
48
+ [local_directory, Confluence.filename].join('/')
49
+ end
50
+
51
+ def prep_command
52
+ noop
53
+ end
54
+
55
+ def cleanup_command
56
+ noop
57
+ end
58
+
59
+
60
+ end
@@ -0,0 +1,69 @@
1
+ require 'date'
2
+ class Mysql < Source
3
+
4
+ def initialize(reader)
5
+ @reader = reader
6
+ end
7
+
8
+ def self.attribute_symbols
9
+ [:source_type, :host, :username, :db_user, :password,
10
+ :db_password, :database, :dump_options, :remote_path, :local_path ]
11
+ end
12
+
13
+ def self.default_source_type
14
+ "Mysql"
15
+ end
16
+
17
+ def self.default_host
18
+ "yourhost.com"
19
+ end
20
+
21
+ def self.default_username
22
+ "username"
23
+ end
24
+
25
+ def self.default_db_user
26
+ "username"
27
+ end
28
+
29
+ def self.default_password
30
+ "password"
31
+ end
32
+
33
+ def self.default_db_password
34
+ "password"
35
+ end
36
+
37
+ def self.default_database
38
+ "test"
39
+ end
40
+
41
+ def self.default_remote_path
42
+ "/path/to/remote/sql-file"
43
+ end
44
+
45
+ def self.default_local_path
46
+ "/path/to/local/sql-file"
47
+ end
48
+
49
+ def self.default_dump_options
50
+ ""
51
+ end
52
+
53
+ def remote_backup_path
54
+ remote_path
55
+ end
56
+
57
+ def local_backup_path
58
+ local_path
59
+ end
60
+
61
+ def prep_command
62
+ "mysqldump #{dump_options} -u #{db_user} --password=#{db_password} #{database} > #{remote_backup_path}"
63
+ end
64
+
65
+ def cleanup_command
66
+ noop
67
+ end
68
+
69
+ end
@@ -0,0 +1,55 @@
1
+ class Subversion < Source
2
+
3
+ def initialize(reader)
4
+ @reader = reader
5
+ end
6
+
7
+ def self.attribute_symbols
8
+ [:source_type, :host, :user, :password, :repository, :remote_path, :local_path ]
9
+ end
10
+
11
+ def self.default_source_type
12
+ "Subversion"
13
+ end
14
+
15
+ def self.default_host
16
+ "yourhost.com"
17
+ end
18
+
19
+ def self.default_user
20
+ "username"
21
+ end
22
+
23
+ def self.default_password
24
+ "password"
25
+ end
26
+
27
+ def self.default_repository
28
+ "/path/to/repo"
29
+ end
30
+
31
+ def self.default_remote_path
32
+ "/path/to/remote/backup-file"
33
+ end
34
+
35
+ def self.default_local_path
36
+ "/path/to/local/backup-file"
37
+ end
38
+
39
+ def remote_backup_path
40
+ remote_path
41
+ end
42
+
43
+ def local_backup_path
44
+ local_path
45
+ end
46
+
47
+ def prep_command
48
+ "svnadmin dump #{repository} > #{remote_backup_path}"
49
+ end
50
+
51
+ def cleanup_command
52
+ noop
53
+ end
54
+
55
+ end
@@ -0,0 +1,6 @@
1
+ class Sink
2
+
3
+ attr_accessor :backup_file
4
+ include Utils
5
+
6
+ end
@@ -0,0 +1,8 @@
1
+ class Source
2
+ include Utils
3
+
4
+ def initialize(attributes)
5
+ @attributes = attributes
6
+ end
7
+
8
+ end
@@ -0,0 +1,31 @@
1
+ module Utils
2
+
3
+ def method_missing(symbol)
4
+ @reader.send(symbol)
5
+ rescue
6
+ nil
7
+ end
8
+
9
+ # remote noop command
10
+ def noop
11
+ "echo"
12
+ end
13
+
14
+ module ClassMethods; end
15
+ def self.included(klass)
16
+ klass.extend(ClassMethods)
17
+ end
18
+
19
+ module ClassMethods
20
+ def default_attributes
21
+ atts = {}
22
+ attribute_symbols.each do |sym|
23
+ sym_string = "default_"+sym.to_s
24
+ default_sym = sym_string.to_sym
25
+ val = self.send(default_sym)
26
+ atts[sym.to_s] = val
27
+ end
28
+ atts
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,55 @@
1
+ gem 'blanket'
2
+ require 'blanket/init'
3
+ Capistrano::Configuration.instance(:must_exist).load do
4
+ namespace :source do
5
+
6
+ desc "Load configuration into Capistrano"
7
+ task :load_config do
8
+ reader = Blanket::Reader.new(FileUtils.pwd+"/source.yml")
9
+ reader.keys.each do |key|
10
+ set key.to_sym, reader.send(key)
11
+ end
12
+ set :source, Object.const_get(source_type).new(reader)
13
+ end
14
+
15
+ desc "Prepare a backup for download"
16
+ task :prep, :hosts => lambda{ host } do
17
+ run variables[:source].prep_command
18
+ end
19
+
20
+ desc "Download the prepped backup"
21
+ task :download, :hosts => lambda{ host } do
22
+ get variables[:source].remote_backup_path, variables[:source].local_backup_path
23
+ end
24
+
25
+ desc "Clean up, remotely"
26
+ task :cleanup, :hosts => lambda{ host } do
27
+ run variables[:source].cleanup_command
28
+ end
29
+
30
+ end
31
+ before "source:prep", "source:load_config"
32
+ before "source:download", "source:prep"
33
+ after "source:download", "source:cleanup"
34
+
35
+ namespace :sink do
36
+
37
+ desc "Load configuration into Capistrano"
38
+ task :load_config do
39
+ reader = Blanket::Reader.new(FileUtils.pwd+"/sink.yml")
40
+ reader.keys.each do |key|
41
+ set key.to_sym, reader.send(key)
42
+ end
43
+ set :sink, Object.const_get(sink_type).new(reader)
44
+ end
45
+
46
+ desc "Send file to sink"
47
+ task :export do
48
+ upload_filename = Pathname.new(variables[:source].local_backup_path).basename.to_s
49
+ variables[:sink].drain(bucket, upload_filename)
50
+ end
51
+
52
+ end
53
+ before "sink:export", "source:download"
54
+ before "sink:export", "sink:load_config"
55
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + "/spec_helper.rb"
2
+
3
+ describe "The Confluence source" do
4
+
5
+ before(:each) do
6
+ @file = File.dirname(__FILE__) + "/fixtures/confluence.yml"
7
+ @reader = Reader.new(@file)
8
+ @instance = Confluence.new(@reader)
9
+ @date_string = Date.today.strftime("%Y_%m_%d")
10
+ end
11
+
12
+ it "should give back an accurate set of default attributes" do
13
+ atts = Confluence.default_attributes
14
+ atts["host"].should == "yourhost.com"
15
+ end
16
+
17
+ it "should delegate methods to its configuration" do
18
+ @instance.source_type.should == "Confluence"
19
+ @instance.remote_directory.should == "/path/to/remote/backups"
20
+ end
21
+
22
+ it "should assemble the remote backup path properly" do
23
+ @instance.remote_backup_path.should == "/path/to/remote/backups/daily-backup-#{@date_string}.zip"
24
+ end
25
+
26
+ it "should assemble the local backup path properly" do
27
+ @instance.local_backup_path.should == "/path/to/local/backups/daily-backup-#{@date_string}.zip"
28
+ end
29
+
30
+ end
@@ -0,0 +1,20 @@
1
+ #load File.dirname(__FILE__) + "/spec_helper.rb"
2
+ # Don't include the spec helper here to determine
3
+
4
+ describe "To run the app" do
5
+
6
+ it "you should have the aws-s3 gem installed" do
7
+ lambda{
8
+ require 'rubygems'
9
+ gem 'aws-s3'
10
+ }.should_not raise_error
11
+ end
12
+
13
+ it "you should have the capistrano gem installed" do
14
+ lambda{
15
+ require 'rubygems'
16
+ gem 'capistrano'
17
+ }.should_not raise_error
18
+ end
19
+
20
+ end
@@ -0,0 +1,7 @@
1
+ ---
2
+ user: username
3
+ remote_directory: /path/to/remote/confluence/backups
4
+ local_directory: /path/to/local/confluence/backups
5
+ host: yourhost.com
6
+ source_type: Confluence
7
+ password: password
@@ -0,0 +1,5 @@
1
+ ---
2
+ access_key_id: your-id
3
+ secret_access_key: your-secret-ket
4
+ bucket: s3-bucket
5
+ sink_type: S3
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + "/spec_helper.rb"
2
+
3
+ describe "The YAML config file" do
4
+
5
+ describe "for S3" do
6
+ before do
7
+ file = File.dirname(__FILE__) + "/fixtures/s3-info.yml"
8
+ @reader = Reader.new(file)
9
+ end
10
+
11
+ it "should instantiate a reader from a file" do
12
+ @reader.should_not be_nil
13
+ end
14
+
15
+ it "should define the sink type as S3" do
16
+ @reader.sink_type.should == "S3"
17
+ end
18
+
19
+
20
+ it "should define the access key id" do
21
+ @reader.access_key_id.should == "some_key"
22
+ end
23
+
24
+ it "should define the secret key id" do
25
+ @reader.secret_access_key.should == "some_secret"
26
+ end
27
+
28
+ it "should report the S3 keys as its own" do
29
+ @reader.keys.should == S3.attribute_symbols
30
+ end
31
+
32
+
33
+ end
34
+
35
+ describe "for Confluence" do
36
+ before do
37
+ file = File.dirname(__FILE__) + "/fixtures/confluence.yml"
38
+ @reader = Reader.new(file)
39
+ end
40
+
41
+ it "should define the blanket type as Confluence" do
42
+ @reader.source_type.should == "Confluence"
43
+ end
44
+
45
+ it "should define the host" do
46
+ @reader.host.should == "foobar.com"
47
+ end
48
+
49
+ it "should define the user" do
50
+ @reader.user.should == "foo"
51
+ end
52
+
53
+ it "should define the password" do
54
+ @reader.password.should == "topsecret"
55
+ end
56
+
57
+ it "should define the backup directory" do
58
+ @reader.directory.should == "/var/confluence/backups"
59
+ end
60
+
61
+ it "should define the bucket name" do
62
+ @reader.bucket.should == "com.foobar.confluence"
63
+ end
64
+
65
+ it "should report the Confluence keys as its own" do
66
+ @reader.keys.should == Confluence.attribute_symbols
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + "/spec_helper.rb"
2
+
3
+ describe "The S3 sink" do
4
+
5
+ it "should give back an accurate set of default attributes" do
6
+ atts = S3.default_attributes
7
+ atts["access_key_id"].should == "your-id"
8
+ end
9
+
10
+ end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/../lib/init.rb"
2
+ gem 'rspec'
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + "/spec_helper.rb"
2
+
3
+ describe "The Blanket config writer" do
4
+
5
+ before do
6
+ @confluence_file = File.dirname(__FILE__) + "/fixtures/confluence.yml"
7
+ @atts = YAML.load_file(@confluence_file)
8
+ @writer = Writer.new(@atts)
9
+ @tempfile = File.dirname(__FILE__)+"/tmp/temp.yml"
10
+ end
11
+
12
+ it "should write a config file that the reader can read" do
13
+ @writer.write(@tempfile)
14
+ reader = Reader.new(@tempfile)
15
+ Reader.new(@tempfile).source_type.should == "Confluence"
16
+ end
17
+
18
+ it "should write a config file that matches the incoming parameters" do
19
+ @writer.write(@tempfile)
20
+ @reader = Reader.new(@confluence_file)
21
+ @write_reader = Reader.new(@tempfile)
22
+ [:sink_type, :host, :user, :password, :directory, :bucket].each do |sym|
23
+ @write_reader.send(sym).should == @reader.send(sym)
24
+ end
25
+ end
26
+
27
+ it "should fail gracefully if it can't write the config file for whatever reason"
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blanket
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jim Van Fleet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-02 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.0
23
+ - - <
24
+ - !ruby/object:Gem::Version
25
+ version: 2.99.0
26
+ version:
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws-s3
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.4.0
35
+ - - <
36
+ - !ruby/object:Gem::Version
37
+ version: "1.0"
38
+ version:
39
+ description:
40
+ email: jim@jimvanfleet.com
41
+ executables:
42
+ - blanket
43
+ - blanket-cfg
44
+ extensions: []
45
+
46
+ extra_rdoc_files: []
47
+
48
+ files:
49
+ - bin/blanket
50
+ - bin/blanket-cfg
51
+ - lib/blanket/config
52
+ - lib/blanket/config/reader.rb
53
+ - lib/blanket/config/writer.rb
54
+ - lib/blanket/init.rb
55
+ - lib/blanket/sink.rb
56
+ - lib/blanket/source.rb
57
+ - lib/blanket/utils.rb
58
+ - lib/capistrano/recipes
59
+ - lib/capistrano/recipes/blanket.rb
60
+ - lib/blanket/plugins/sources
61
+ - lib/blanket/plugins/sources/confluence.rb
62
+ - lib/blanket/plugins/sources/mysql.rb
63
+ - lib/blanket/plugins/sources/subversion.rb
64
+ - lib/blanket/plugins/sinks/s3.rb
65
+ - spec/fixtures
66
+ - spec/confluence_spec.rb
67
+ - spec/dependency_spec.rb
68
+ - spec/fixtures/confluence.yml
69
+ - spec/fixtures/s3-info.yml
70
+ - spec/reader_spec.rb
71
+ - spec/s3_spec.rb
72
+ - spec/spec_helper.rb
73
+ - spec/writer_spec.rb
74
+ - README
75
+ - MIT-LICENSE
76
+ has_rdoc: false
77
+ homepage: http://www.jimvanfleet.com/projects/blanket
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: "0"
88
+ version:
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: "0"
94
+ version:
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.0.1
99
+ signing_key:
100
+ specification_version: 2
101
+ summary: Blanket is a flexible backup framework designed to get the drudgery out of the way and to make automated backups easy.
102
+ test_files: []
103
+