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.
- data/MIT-LICENSE +20 -0
- data/README +3 -0
- data/bin/blanket +7 -0
- data/bin/blanket-cfg +80 -0
- data/lib/blanket/config/reader.rb +31 -0
- data/lib/blanket/config/writer.rb +15 -0
- data/lib/blanket/init.rb +21 -0
- data/lib/blanket/plugins/sinks/s3.rb +67 -0
- data/lib/blanket/plugins/sources/confluence.rb +60 -0
- data/lib/blanket/plugins/sources/mysql.rb +69 -0
- data/lib/blanket/plugins/sources/subversion.rb +55 -0
- data/lib/blanket/sink.rb +6 -0
- data/lib/blanket/source.rb +8 -0
- data/lib/blanket/utils.rb +31 -0
- data/lib/capistrano/recipes/blanket.rb +55 -0
- data/spec/confluence_spec.rb +30 -0
- data/spec/dependency_spec.rb +20 -0
- data/spec/fixtures/confluence.yml +7 -0
- data/spec/fixtures/s3-info.yml +5 -0
- data/spec/reader_spec.rb +73 -0
- data/spec/s3_spec.rb +10 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/writer_spec.rb +29 -0
- metadata +103 -0
data/MIT-LICENSE
ADDED
@@ -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
data/bin/blanket
ADDED
data/bin/blanket-cfg
ADDED
@@ -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
|
data/lib/blanket/init.rb
ADDED
@@ -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
|
data/lib/blanket/sink.rb
ADDED
@@ -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
|
data/spec/reader_spec.rb
ADDED
@@ -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
|
+
|
data/spec/s3_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
data/spec/writer_spec.rb
ADDED
@@ -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
|
+
|