monsoon 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/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Guardfile +4 -0
- data/LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/lib/monsoon/backup.rb +79 -0
- data/lib/monsoon/client.rb +77 -0
- data/lib/monsoon/compress.rb +60 -0
- data/lib/monsoon/store.rb +55 -0
- data/lib/monsoon/version.rb +3 -0
- data/lib/monsoon.rb +39 -0
- data/monsoon.gemspec +26 -0
- data/spec/monsoon/backup_spec.rb +143 -0
- data/spec/monsoon/client_spec.rb +128 -0
- data/spec/monsoon/compress_spec.rb +76 -0
- data/spec/monsoon/store_spec.rb +77 -0
- data/spec/monsoon_spec.rb +48 -0
- data/spec/spec_helper.rb +7 -0
- metadata +116 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Brandon Hilkert
|
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.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Monsoon Gem
|
2
|
+
=======================
|
3
|
+
|
4
|
+
Monsoon is a MongoDB backup tool that allows you to take backups and store them in Amazon S3.
|
5
|
+
|
6
|
+
|
7
|
+
Usage
|
8
|
+
-----
|
9
|
+
|
10
|
+
To install:
|
11
|
+
|
12
|
+
gem install monsoon
|
13
|
+
|
14
|
+
To Configure:
|
15
|
+
|
16
|
+
Monsoon.configure do |config|
|
17
|
+
config.bucket = "mongo_backups"
|
18
|
+
config.key = "my_super_secret_aws_key"
|
19
|
+
config.secret = "my_super_secret_aws_secret"
|
20
|
+
config.backup_directory = "tmp"
|
21
|
+
config.mongo_uri = "mongodb://user:password@test.mongohq.com:10036/add_development"
|
22
|
+
end
|
23
|
+
|
24
|
+
To use:
|
25
|
+
|
26
|
+
client = Monsoon::Client.new
|
27
|
+
client.run
|
28
|
+
|
29
|
+
|
30
|
+
Requirements
|
31
|
+
----
|
32
|
+
|
33
|
+
`mongodump` must be installed on the system and available from anywhere on in the console.
|
34
|
+
|
35
|
+
The gem also utilizes `tar` to compress the back so this, too, must be accessible form the command line.
|
36
|
+
|
37
|
+
Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php).
|
38
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
class Backup
|
5
|
+
|
6
|
+
attr_reader :backup_directory
|
7
|
+
|
8
|
+
def initialize(uri, backup_directory = "tmp")
|
9
|
+
@uri = uri
|
10
|
+
@backup_directory = backup_directory
|
11
|
+
end
|
12
|
+
|
13
|
+
# Run the Monsoon Backup process.
|
14
|
+
#
|
15
|
+
# Examples
|
16
|
+
#
|
17
|
+
# Monsoon::Backup("mongodb://@test.mongohq.com:10036/app_development").run
|
18
|
+
# # => #<Monsoon::Backup>
|
19
|
+
#
|
20
|
+
# Returns an instance of the Monsoon::Backup class
|
21
|
+
def run
|
22
|
+
Kernel.system "#{mongo_dump_command}"
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates the config hash for the connection string
|
27
|
+
#
|
28
|
+
# Examples
|
29
|
+
#
|
30
|
+
# Monsoon::Backup("mongodb://test.mongohq.com:10036/app_development").config
|
31
|
+
# # => {"host" => "test.mongohq.com",
|
32
|
+
# "post" => 10036,
|
33
|
+
# "database" => "app_development",
|
34
|
+
# "username" => "testuser",
|
35
|
+
# "password" => "pass1"}
|
36
|
+
#
|
37
|
+
# Returns an instance of the Monsoon::Backup class
|
38
|
+
def config
|
39
|
+
return {} unless @uri
|
40
|
+
|
41
|
+
uri = URI.parse(@uri)
|
42
|
+
raise "must be a mongo DB" unless uri.scheme == 'mongodb'
|
43
|
+
{
|
44
|
+
"host" => uri.host,
|
45
|
+
"port" => uri.port,
|
46
|
+
"database" => uri.path.gsub(/^\//, ''),
|
47
|
+
"username" => uri.user,
|
48
|
+
"password" => uri.password
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# Helper method for database name.
|
53
|
+
#
|
54
|
+
# Examples
|
55
|
+
#
|
56
|
+
# Monsoon::Backup("mongodb://test.mongohq.com:10036/app_development").database
|
57
|
+
# # => "app_development"
|
58
|
+
#
|
59
|
+
# Returns a String of the database name.
|
60
|
+
def database
|
61
|
+
config["database"]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Helper to form the mongodump command.
|
65
|
+
#
|
66
|
+
# Examples
|
67
|
+
#
|
68
|
+
# Monsoon::Backup("mongodb://test.mongohq.com:10036/app_development").mongo_dump_command
|
69
|
+
# # => "mongodump -h test.mongohq.com:10036 -d app_development -o tmp"
|
70
|
+
#
|
71
|
+
# Returns the command as a String.
|
72
|
+
def mongo_dump_command
|
73
|
+
cmd = ""
|
74
|
+
cmd = "mongodump -h #{config['host']}:#{config['port']} -d #{config['database']} -o #{@backup_directory} "
|
75
|
+
cmd += "--username #{config['username']} --password #{config['password']}" unless config["username"].nil? and config["password"].nil?
|
76
|
+
cmd
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Monsoon
|
2
|
+
class Client
|
3
|
+
|
4
|
+
def initialize(bucket = Monsoon.bucket, key = Monsoon.key, secret = Monsoon.secret, backup_directory = Monsoon.backup_directory, mongo_uri = Monsoon.mongo_uri)
|
5
|
+
@bucket = bucket
|
6
|
+
@key = key
|
7
|
+
@secret = secret
|
8
|
+
@backup_directory = backup_directory
|
9
|
+
@mongo_uri = mongo_uri
|
10
|
+
end
|
11
|
+
|
12
|
+
# Run the Monsoon process to backup, save, and clean the work.
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
#
|
16
|
+
# Monsoon::Client.new.run
|
17
|
+
# # => True
|
18
|
+
#
|
19
|
+
# Returns True
|
20
|
+
def run
|
21
|
+
# Backup the MongoDB database to filesystem
|
22
|
+
b = backup.run
|
23
|
+
|
24
|
+
# Compress the contents of the backup
|
25
|
+
c = compress(b).run
|
26
|
+
|
27
|
+
# Sent to AWS
|
28
|
+
store(c.filename).save
|
29
|
+
|
30
|
+
# Remove the compressed file from the filesystem
|
31
|
+
c.clean
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
# Creates an instance of the Monsoon::Backup class
|
37
|
+
#
|
38
|
+
# Examples
|
39
|
+
#
|
40
|
+
# Monsoon::Client.new.backup
|
41
|
+
# # => #<Monsoon::Backup>
|
42
|
+
#
|
43
|
+
# Returns an instance of the Monsoon::Client object
|
44
|
+
def backup
|
45
|
+
Backup.new(@mongo_uri, @backup_directory)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates an instnace of the Monsoon::Compress class
|
49
|
+
#
|
50
|
+
# backup - The Monsoon::Backup instance the preceeded.
|
51
|
+
#
|
52
|
+
# Examples
|
53
|
+
#
|
54
|
+
# Monsoon::Client.new.compress(#<Monsoon::Backup>)
|
55
|
+
# # => #<Monsoon::Compress>
|
56
|
+
#
|
57
|
+
# Returns an instance of the Monsoon::Compress object
|
58
|
+
def compress(backup)
|
59
|
+
Compress.new(backup)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates an instance of the Monsoon::Store class
|
63
|
+
#
|
64
|
+
# filename - The String filename of the compressed backup to push to S3.
|
65
|
+
#
|
66
|
+
# Examples
|
67
|
+
#
|
68
|
+
# Monsoon::Client.new.store("test.tar.gz")
|
69
|
+
# # => #<Monsoon::Store>
|
70
|
+
#
|
71
|
+
# Returns an instance of the Monsoon::Store object
|
72
|
+
def store(filename)
|
73
|
+
Store.new(filename, @bucket, @key, @secret)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
class Compress
|
5
|
+
|
6
|
+
def initialize(backup)
|
7
|
+
@backup = backup
|
8
|
+
end
|
9
|
+
|
10
|
+
# Run the Monsoon Compress process.
|
11
|
+
#
|
12
|
+
# Examples
|
13
|
+
#
|
14
|
+
# Monsoon::Compress(#<Monsoon::Backup>).run
|
15
|
+
# # => #<Monsoon::Compress>
|
16
|
+
#
|
17
|
+
# Returns an instance of the Monsoon::Compress class
|
18
|
+
def run
|
19
|
+
Kernel.system "#{compress_command}"
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Helper to form the tar compress command.
|
24
|
+
#
|
25
|
+
# Examples
|
26
|
+
#
|
27
|
+
# Monsoon::Compress(#<Monsoon::Backup>).compress_command
|
28
|
+
# # => "tar -czf app_development_1234.tar.gz tmp"
|
29
|
+
#
|
30
|
+
# Returns the command as a String.
|
31
|
+
def compress_command
|
32
|
+
"tar -czf #{filename} #{@backup.backup_directory}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Helper to form the tar compress command.
|
36
|
+
#
|
37
|
+
# Examples
|
38
|
+
#
|
39
|
+
# Monsoon::Compress(#<Monsoon::Backup>).filename
|
40
|
+
# # => "app_development_1234.tar.gz"
|
41
|
+
#
|
42
|
+
# Returns the filename as a String.
|
43
|
+
def filename
|
44
|
+
@filename ||= "#{@backup.database}_#{Time.now.utc.to_i.to_s}.tar.gz"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Helper to delete the backup file once finished.
|
48
|
+
#
|
49
|
+
# Examples
|
50
|
+
#
|
51
|
+
# Monsoon::Compress(#<Monsoon::Backup>).clean
|
52
|
+
# # => "app_development_1234.tar.gz"
|
53
|
+
#
|
54
|
+
# Returns results of the command.
|
55
|
+
def clean
|
56
|
+
FileUtils.rm filename, force: true
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
begin
|
2
|
+
require "aws/s3"
|
3
|
+
rescue LoadError
|
4
|
+
raise "You don't have the 'aws' gem installed."
|
5
|
+
end
|
6
|
+
|
7
|
+
module Monsoon
|
8
|
+
class Store
|
9
|
+
|
10
|
+
def initialize(filename, bucket, key, secret)
|
11
|
+
@filename, @bucket, @key, @secret = filename, bucket, key, secret
|
12
|
+
end
|
13
|
+
|
14
|
+
# Runs the Monsoon Store save process.
|
15
|
+
#
|
16
|
+
# Examples
|
17
|
+
#
|
18
|
+
# Monsoon::Store("backup.tar.gz", "backups_bucket", "super_secret_key", "super_secret_secret").save
|
19
|
+
# # => #<AWS::S3::S3Object>
|
20
|
+
#
|
21
|
+
# Returns an instance of the AWS::S3::S3Object class
|
22
|
+
def save
|
23
|
+
connect
|
24
|
+
AWS::S3::S3Object.store(@filename, read_file_contents, @bucket)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Parses the contents of the compressed backup.
|
28
|
+
#
|
29
|
+
# Examples
|
30
|
+
#
|
31
|
+
# Monsoon::Store("backup.tar.gz", "backups_bucket", "super_secret_key", "super_secret_secret").read_file_contents
|
32
|
+
# # => #<AWS::S3::S3Object>
|
33
|
+
#
|
34
|
+
# Returns contents of the binary file.
|
35
|
+
def read_file_contents
|
36
|
+
file = File.open(@filename, "rb")
|
37
|
+
file.read
|
38
|
+
end
|
39
|
+
|
40
|
+
# Connects to AWS.
|
41
|
+
#
|
42
|
+
# Examples
|
43
|
+
#
|
44
|
+
# Monsoon::Store("backup.tar.gz", "backups_bucket", "super_secret_key", "super_secret_secret").connect
|
45
|
+
# # => #<AWS::S3::Connection>
|
46
|
+
#
|
47
|
+
# Returns an instance of the AWS::S3::Connection class.
|
48
|
+
def connect
|
49
|
+
AWS::S3::Base.establish_connection!(
|
50
|
+
:access_key_id => @key,
|
51
|
+
:secret_access_key => @secret
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/monsoon.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Monsoon
|
2
|
+
|
3
|
+
class << self
|
4
|
+
attr_accessor :bucket, :key, :secret, :backup_directory, :mongo_uri
|
5
|
+
|
6
|
+
# config/initializers/monsoon.rb (for instance)
|
7
|
+
#
|
8
|
+
# Monsoon.configure do |config|
|
9
|
+
# config.bucket = 'backups'
|
10
|
+
# config.key = 'consumer_key'
|
11
|
+
# config.secret = 'consumer_secret'
|
12
|
+
# config.backup_directory = 'data'
|
13
|
+
# config.mongo_uri = 'mongodb://testuser:pass1@test.mongohq.com:10036/app_development'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
def configure
|
17
|
+
yield self
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Run the Monsoon process to backup, save, and clean the work.
|
22
|
+
#
|
23
|
+
# Examples
|
24
|
+
#
|
25
|
+
# Monsoon.perform
|
26
|
+
# # => True
|
27
|
+
#
|
28
|
+
# Returns True
|
29
|
+
def perform
|
30
|
+
Monsoon::Client.new.run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
autoload :Backup, "monsoon/backup"
|
35
|
+
autoload :Client, "monsoon/client"
|
36
|
+
autoload :Compress, "monsoon/compress"
|
37
|
+
autoload :Store, "monsoon/store"
|
38
|
+
autoload :Version, "monsoon/version"
|
39
|
+
end
|
data/monsoon.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "monsoon/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "monsoon"
|
7
|
+
s.version = Monsoon::VERSION
|
8
|
+
s.authors = ["Brandon Hilkert"]
|
9
|
+
s.email = ["brandonhilkert@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/brandonhilkert/egg_carton"
|
11
|
+
s.summary = %q{Monsoon MongoDB Backup Utility}
|
12
|
+
s.description = %q{Monsoon is a MongoDB backup tool that allows you to take backups and store them in Amazon S3.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "monsoon"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rspec", "~> 2.8"
|
22
|
+
s.add_development_dependency "guard-rspec"
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
|
25
|
+
s.add_dependency "aws-s3"
|
26
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
|
5
|
+
describe Backup do
|
6
|
+
let(:uri) { "mongodb://testuser:pass1@test.mongohq.com:10036/app_development" }
|
7
|
+
let(:directory) { "tmp" }
|
8
|
+
|
9
|
+
describe "initalization" do
|
10
|
+
let(:backup) { Backup.new(uri) }
|
11
|
+
|
12
|
+
it "should set the @uri instance variable" do
|
13
|
+
backup.instance_variable_get(:@uri).should == uri
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should set the @directory instance variable to default directory if none is provided" do
|
17
|
+
backup.instance_variable_get(:@backup_directory).should == "tmp"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set the @directory instance variable to specified directory" do
|
21
|
+
backup = Backup.new(uri, "tmp/data")
|
22
|
+
backup.instance_variable_get(:@backup_directory).should == "tmp/data"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be able to read backup_directory instance variable" do
|
26
|
+
backup.backup_directory.should == "tmp"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#run" do
|
31
|
+
let(:backup) { Backup.new(uri) }
|
32
|
+
|
33
|
+
before(:each) do
|
34
|
+
backup.stub(:mongo_dump_command).and_return("mongodump -h test -p 10000")
|
35
|
+
Kernel.stub(:system).and_return(nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should run call on system" do
|
39
|
+
Kernel.should_receive(:system).with("mongodump -h test -p 10000")
|
40
|
+
backup.run
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should call mongo_dump method" do
|
44
|
+
backup.should_receive(:mongo_dump_command)
|
45
|
+
backup.run
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return backup instance" do
|
49
|
+
backup.run.should == backup
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#config" do
|
54
|
+
it "should raise error if uri is not a mongodb connection string" do
|
55
|
+
bad_uri = "http://user:pass1@test.mongohq.com:10036/app_development"
|
56
|
+
|
57
|
+
b = Backup.new(bad_uri)
|
58
|
+
expect { raise b.config }.to raise_error
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "with valid URI" do
|
62
|
+
subject{ Backup.new(uri).config }
|
63
|
+
|
64
|
+
it "should return 'test.mongohq.com' as the host" do
|
65
|
+
subject["host"].should == "test.mongohq.com"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should return 10036 as the port" do
|
69
|
+
subject["port"].should == 10036
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return 'app_development' as the database" do
|
73
|
+
subject["database"].should == "app_development"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return 'testuser' as the username" do
|
77
|
+
subject["username"].should == "testuser"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return 'pass1' as the password" do
|
81
|
+
subject["password"].should == "pass1"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#database" do
|
87
|
+
subject{ Backup.new(uri).database }
|
88
|
+
|
89
|
+
it "should return 'app_development' for database" do
|
90
|
+
subject.should == "app_development"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#mongo_dump_command" do
|
95
|
+
subject{ Backup.new(uri).mongo_dump_command }
|
96
|
+
|
97
|
+
it "should include mongo dump command" do
|
98
|
+
subject.should include("mongodump")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should include switch for host including port" do
|
102
|
+
subject.should include("-h test.mongohq.com:10036")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should include switch for database" do
|
106
|
+
subject.should include("-d app_development")
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should include switch for username" do
|
110
|
+
subject.should include("--username testuser")
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should include switch for password" do
|
114
|
+
subject.should include("--password pass1")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should include switch for output directory" do
|
118
|
+
subject.should include("-o tmp")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should change output directory if intialized with it" do
|
122
|
+
Backup.new(uri, "tmp/data").mongo_dump_command.should include("-o tmp/data")
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "when user and password is not included" do
|
127
|
+
let(:backup) { Backup.new("mongodb://test.mongohq.com:10036/app_development").mongo_dump_command }
|
128
|
+
|
129
|
+
it "should not include username switch" do
|
130
|
+
backup.should_not include("--username")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not include password switch" do
|
134
|
+
backup.should_not include("--password")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
|
5
|
+
describe Client do
|
6
|
+
let(:bucket) { "bucket" }
|
7
|
+
let(:key) { "key" }
|
8
|
+
let(:secret) { "secret" }
|
9
|
+
let(:backup_directory) { "tmp" }
|
10
|
+
let(:mongo_uri) { "mongodb://testuser:pass1@test.mongohq.com:10036/app_development" }
|
11
|
+
let(:client) { Monsoon::Client.new(bucket, key, secret, backup_directory, mongo_uri) }
|
12
|
+
|
13
|
+
describe "initalization" do
|
14
|
+
it "should set the @bucket instance variable" do
|
15
|
+
client.instance_variable_get(:@bucket).should == bucket
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should set the @key instance variable" do
|
19
|
+
client.instance_variable_get(:@key).should == key
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should set the @secret instance variable" do
|
23
|
+
client.instance_variable_get(:@secret).should == secret
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should set the @backup_directory instance variable" do
|
27
|
+
client.instance_variable_get(:@backup_directory).should == backup_directory
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set the @mongo_uri instance variable" do
|
31
|
+
client.instance_variable_get(:@mongo_uri).should == mongo_uri
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "config variables" do
|
35
|
+
it "should set instance variable bucket" do
|
36
|
+
Monsoon.bucket = "bucket"
|
37
|
+
c = Monsoon::Client.new
|
38
|
+
c.instance_variable_get(:@bucket).should == "bucket"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should set instance variable key" do
|
42
|
+
Monsoon.key = "key"
|
43
|
+
c = Monsoon::Client.new
|
44
|
+
c.instance_variable_get(:@key).should == "key"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should set instance variable secret" do
|
48
|
+
Monsoon.secret = "secret"
|
49
|
+
c = Monsoon::Client.new
|
50
|
+
c.instance_variable_get(:@secret).should == "secret"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should set instance variable backup_directory" do
|
54
|
+
Monsoon.backup_directory = "tmp/data"
|
55
|
+
c = Monsoon::Client.new
|
56
|
+
c.instance_variable_get(:@backup_directory).should == "tmp/data"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should set instance variable mongo_uri" do
|
60
|
+
Monsoon.mongo_uri = "mongo://localhost"
|
61
|
+
c = Monsoon::Client.new
|
62
|
+
c.instance_variable_get(:@mongo_uri).should == "mongo://localhost"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#run" do
|
69
|
+
let(:backup) { Backup.new(mongo_uri, backup_directory) }
|
70
|
+
let(:compress) { Compress.new(backup) }
|
71
|
+
let(:store) { Store.new(compress, bucket, key, secret) }
|
72
|
+
|
73
|
+
before(:each) do
|
74
|
+
Backup.any_instance.stub(:run).and_return(backup)
|
75
|
+
Compress.any_instance.stub(:run).and_return(compress)
|
76
|
+
Store.any_instance.stub(:save).and_return(store)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should run the backup process" do
|
80
|
+
Backup.any_instance.should_receive(:run)
|
81
|
+
client.run
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should run the compress process" do
|
85
|
+
Compress.any_instance.should_receive(:run)
|
86
|
+
client.run
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should run the store process" do
|
90
|
+
Store.any_instance.should_receive(:save)
|
91
|
+
client.run
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should remove the compressed file" do
|
95
|
+
compress.should_receive(:clean)
|
96
|
+
client.run
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#backup" do
|
101
|
+
it "should initalize a new Backup object" do
|
102
|
+
Backup.should_receive(:new).with(mongo_uri, backup_directory)
|
103
|
+
client.backup
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#compress" do
|
108
|
+
let(:backup) { Backup.new(mongo_uri, backup_directory) }
|
109
|
+
|
110
|
+
it "should initalize a new Compress object" do
|
111
|
+
Compress.should_receive(:new).with(backup)
|
112
|
+
client.compress(backup)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "#store" do
|
117
|
+
let(:backup) { Backup.new(mongo_uri, backup_directory) }
|
118
|
+
let(:compress) { Compress.new(backup) }
|
119
|
+
|
120
|
+
it "should initalize a new Compress object" do
|
121
|
+
Compress.should_receive(:new).with(compress, bucket, key, secret)
|
122
|
+
client.store(compress)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
|
5
|
+
describe Compress do
|
6
|
+
let(:backup) { double("backup", backup_directory: "tmp", database: "app_development") }
|
7
|
+
let(:compress) { Compress.new(backup) }
|
8
|
+
|
9
|
+
describe "initalization" do
|
10
|
+
it "should set the @directory instance variable" do
|
11
|
+
compress.instance_variable_get(:@backup).should == backup
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#run" do
|
16
|
+
before(:each) do
|
17
|
+
compress.stub(:compress_command).and_return("tar -czf")
|
18
|
+
Kernel.stub(:system).and_return(nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should run call on system" do
|
22
|
+
Kernel.should_receive(:system).with("tar -czf")
|
23
|
+
compress.run
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should call compress method" do
|
27
|
+
compress.should_receive(:compress_command)
|
28
|
+
compress.run
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return compress instance" do
|
32
|
+
compress.run.should == compress
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#compress_command" do
|
37
|
+
it "should include the tar command" do
|
38
|
+
compress.compress_command.should include("tar -czf")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should include filename with timestamp and tar.gz extension" do
|
42
|
+
compress.stub(:filename).and_return("app_development.1234.tar.gz")
|
43
|
+
compress.compress_command.should include("app_development.1234.tar.gz")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#filename" do
|
48
|
+
it "should return the correct filename with timestamp" do
|
49
|
+
Time.stub_chain(:now, :utc, :to_i, :to_s).and_return("1234")
|
50
|
+
compress.filename.should == "app_development_1234.tar.gz"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return original filename if subsequently requseted" do
|
54
|
+
Time.stub_chain(:now, :utc, :to_i, :to_s).and_return("1234")
|
55
|
+
filename = compress.filename
|
56
|
+
Time.stub_chain(:now, :utc, :to_i, :to_s).and_return("0000")
|
57
|
+
compress.filename.should == filename
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#clean" do
|
62
|
+
let(:filename) { compress.filename }
|
63
|
+
|
64
|
+
it "should trigger the rm command" do
|
65
|
+
FileUtils.should_receive(:rm).with(filename, force: true)
|
66
|
+
compress.clean
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should delete a file" do
|
70
|
+
File
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Monsoon
|
4
|
+
|
5
|
+
describe Store do
|
6
|
+
let(:store) { Store.new("app_development.tar.gz", "backups", "key", "secret") }
|
7
|
+
|
8
|
+
describe "initalization" do
|
9
|
+
it "should set the @filename instance variable" do
|
10
|
+
store.instance_variable_get(:@filename).should == "app_development.tar.gz"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should set the @key instance variable" do
|
14
|
+
store.instance_variable_get(:@key).should == "key"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set the @secret instance variable" do
|
18
|
+
store.instance_variable_get(:@secret).should == "secret"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set the @bucket instance variable" do
|
22
|
+
store.instance_variable_get(:@bucket).should == "backups"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#save" do
|
28
|
+
before(:each) do
|
29
|
+
AWS::S3::S3Object.stub(:store).and_return(AWS::S3::S3Object)
|
30
|
+
store.stub(:read_file_contents).and_return("test")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should connect to AWS" do
|
34
|
+
store.should_receive(:connect)
|
35
|
+
store.save
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should execute store method on fog S3Object" do
|
39
|
+
AWS::S3::S3Object.should_receive(:store).with("app_development.tar.gz", "test", "backups")
|
40
|
+
store.save
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should call the read_file_contents method" do
|
44
|
+
store.should_receive(:read_file_contents)
|
45
|
+
store.save
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#read_file_contents" do
|
50
|
+
before(:each) do
|
51
|
+
File.stub(:open).with("app_development.tar.gz", "rb").and_return("test")
|
52
|
+
String.any_instance.stub(:read).and_return("test")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should open the File" do
|
56
|
+
File.should_receive(:open).with("app_development.tar.gz", "rb")
|
57
|
+
store.read_file_contents
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should execute the read operation on the file object" do
|
61
|
+
String.any_instance.should_receive(:read)
|
62
|
+
store.read_file_contents
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#connect" do
|
67
|
+
subject{ store.connection }
|
68
|
+
|
69
|
+
it "should connect to AWS" do
|
70
|
+
AWS::S3::Base.should_receive(:establish_connection!).with(:access_key_id => "key", :secret_access_key => "secret")
|
71
|
+
store.connect
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Monsoon do
|
4
|
+
before(:each) do
|
5
|
+
Monsoon.bucket = nil
|
6
|
+
Monsoon.key = nil
|
7
|
+
Monsoon.secret = nil
|
8
|
+
Monsoon.backup_directory = nil
|
9
|
+
Monsoon.mongo_uri = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be able to set AWS properties" do
|
13
|
+
Monsoon.bucket = "backups"
|
14
|
+
Monsoon.key = "key"
|
15
|
+
Monsoon.secret = "secret"
|
16
|
+
|
17
|
+
Monsoon.bucket.should == "backups"
|
18
|
+
Monsoon.key.should == "key"
|
19
|
+
Monsoon.secret.should == "secret"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to set options through configure block" do
|
23
|
+
Monsoon.configure do |config|
|
24
|
+
config.bucket = "backups"
|
25
|
+
config.key = "key"
|
26
|
+
config.secret = "secret"
|
27
|
+
config.backup_directory = "tmp/data"
|
28
|
+
config.mongo_uri = "mongodb://testuser:pass1@test.mongohq.com:10036/app_development"
|
29
|
+
end
|
30
|
+
|
31
|
+
Monsoon.bucket.should == "backups"
|
32
|
+
Monsoon.key.should == "key"
|
33
|
+
Monsoon.secret.should == "secret"
|
34
|
+
Monsoon.backup_directory.should == "tmp/data"
|
35
|
+
Monsoon.mongo_uri.should == "mongodb://testuser:pass1@test.mongohq.com:10036/app_development"
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".perform" do
|
39
|
+
before(:each) do
|
40
|
+
Monsoon::Client.any_instance.stub(:run).and_return(true)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should excute the run method on a client instance" do
|
44
|
+
Monsoon::Client.any_instance.should_receive(:run)
|
45
|
+
Monsoon.perform
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monsoon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brandon Hilkert
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-17 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70222012651180 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.8'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70222012651180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: guard-rspec
|
27
|
+
requirement: &70222012650760 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70222012650760
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70222012650300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70222012650300
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: aws-s3
|
49
|
+
requirement: &70222024478080 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70222024478080
|
58
|
+
description: Monsoon is a MongoDB backup tool that allows you to take backups and
|
59
|
+
store them in Amazon S3.
|
60
|
+
email:
|
61
|
+
- brandonhilkert@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .rspec
|
68
|
+
- Gemfile
|
69
|
+
- Guardfile
|
70
|
+
- LICENSE
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- lib/monsoon.rb
|
74
|
+
- lib/monsoon/backup.rb
|
75
|
+
- lib/monsoon/client.rb
|
76
|
+
- lib/monsoon/compress.rb
|
77
|
+
- lib/monsoon/store.rb
|
78
|
+
- lib/monsoon/version.rb
|
79
|
+
- monsoon.gemspec
|
80
|
+
- spec/monsoon/backup_spec.rb
|
81
|
+
- spec/monsoon/client_spec.rb
|
82
|
+
- spec/monsoon/compress_spec.rb
|
83
|
+
- spec/monsoon/store_spec.rb
|
84
|
+
- spec/monsoon_spec.rb
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
homepage: https://github.com/brandonhilkert/egg_carton
|
87
|
+
licenses: []
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project: monsoon
|
106
|
+
rubygems_version: 1.8.10
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Monsoon MongoDB Backup Utility
|
110
|
+
test_files:
|
111
|
+
- spec/monsoon/backup_spec.rb
|
112
|
+
- spec/monsoon/client_spec.rb
|
113
|
+
- spec/monsoon/compress_spec.rb
|
114
|
+
- spec/monsoon/store_spec.rb
|
115
|
+
- spec/monsoon_spec.rb
|
116
|
+
- spec/spec_helper.rb
|