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