blanket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+