kellerkind 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +73 -0
- data/LICENSE.txt +20 -0
- data/README.md +45 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/kellerkind +38 -0
- data/kellerkind.gemspec +85 -0
- data/lib/kellerkind/core/configuration.rb +64 -0
- data/lib/kellerkind/core/ext.rb +8 -0
- data/lib/kellerkind/core/set.rb +16 -0
- data/lib/kellerkind/database/mongo.rb +59 -0
- data/lib/kellerkind/dependencies.rb +9 -0
- data/lib/kellerkind/system/compress.rb +59 -0
- data/lib/kellerkind/system/die.rb +9 -0
- data/lib/kellerkind/system/lock.rb +19 -0
- data/lib/kellerkind/system/runner.rb +56 -0
- data/lib/kellerkind.rb +12 -0
- data/spec/fixtures/mongodb.js +8 -0
- data/spec/kellerkind/database/mongo_spec.rb +145 -0
- data/spec/kellerkind/system/compress_spec.rb +58 -0
- data/spec/kellerkind/system/lock_spec.rb +39 -0
- data/spec/kellerkind/tmp/.gitkeep +0 -0
- data/spec/kellerkind_spec.rb +7 -0
- data/spec/spec_helper.rb +12 -0
- metadata +190 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
gem 'virtus', "~> 0.5.5"
|
7
|
+
gem "minitar", "~> 0.5.4"
|
8
|
+
gem "trollop"
|
9
|
+
|
10
|
+
# Add dependencies to develop your gem here.
|
11
|
+
# Include everything needed to run rake, tests, features, etc.
|
12
|
+
group :development do
|
13
|
+
gem "rspec", "~> 2.13.0"
|
14
|
+
gem "rdoc", "~> 3.12"
|
15
|
+
gem "bundler", "~> 1.3.5"
|
16
|
+
gem "jeweler", "~> 1.8.4"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.3.5)
|
5
|
+
backports (3.3.3)
|
6
|
+
builder (3.2.2)
|
7
|
+
descendants_tracker (0.0.1)
|
8
|
+
diff-lcs (1.2.4)
|
9
|
+
faraday (0.8.7)
|
10
|
+
multipart-post (~> 1.1)
|
11
|
+
git (1.2.5)
|
12
|
+
github_api (0.10.1)
|
13
|
+
addressable
|
14
|
+
faraday (~> 0.8.1)
|
15
|
+
hashie (>= 1.2)
|
16
|
+
multi_json (~> 1.4)
|
17
|
+
nokogiri (~> 1.5.2)
|
18
|
+
oauth2
|
19
|
+
hashie (2.0.5)
|
20
|
+
highline (1.6.19)
|
21
|
+
httpauth (0.2.0)
|
22
|
+
jeweler (1.8.6)
|
23
|
+
builder
|
24
|
+
bundler (~> 1.0)
|
25
|
+
git (>= 1.2.5)
|
26
|
+
github_api (= 0.10.1)
|
27
|
+
highline (>= 1.6.15)
|
28
|
+
nokogiri (= 1.5.10)
|
29
|
+
rake
|
30
|
+
rdoc
|
31
|
+
json (1.8.0)
|
32
|
+
jwt (0.1.8)
|
33
|
+
multi_json (>= 1.5)
|
34
|
+
minitar (0.5.4)
|
35
|
+
multi_json (1.7.7)
|
36
|
+
multi_xml (0.5.4)
|
37
|
+
multipart-post (1.2.0)
|
38
|
+
nokogiri (1.5.10)
|
39
|
+
oauth2 (0.9.2)
|
40
|
+
faraday (~> 0.8)
|
41
|
+
httpauth (~> 0.2)
|
42
|
+
jwt (~> 0.1.4)
|
43
|
+
multi_json (~> 1.0)
|
44
|
+
multi_xml (~> 0.5)
|
45
|
+
rack (~> 1.2)
|
46
|
+
rack (1.5.2)
|
47
|
+
rake (10.1.0)
|
48
|
+
rdoc (3.12.2)
|
49
|
+
json (~> 1.4)
|
50
|
+
rspec (2.13.0)
|
51
|
+
rspec-core (~> 2.13.0)
|
52
|
+
rspec-expectations (~> 2.13.0)
|
53
|
+
rspec-mocks (~> 2.13.0)
|
54
|
+
rspec-core (2.13.1)
|
55
|
+
rspec-expectations (2.13.0)
|
56
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
57
|
+
rspec-mocks (2.13.1)
|
58
|
+
trollop (2.0)
|
59
|
+
virtus (0.5.5)
|
60
|
+
backports (~> 3.3)
|
61
|
+
descendants_tracker (~> 0.0.1)
|
62
|
+
|
63
|
+
PLATFORMS
|
64
|
+
ruby
|
65
|
+
|
66
|
+
DEPENDENCIES
|
67
|
+
bundler (~> 1.3.5)
|
68
|
+
jeweler (~> 1.8.4)
|
69
|
+
minitar (~> 0.5.4)
|
70
|
+
rdoc (~> 3.12)
|
71
|
+
rspec (~> 2.13.0)
|
72
|
+
trollop
|
73
|
+
virtus (~> 0.5.5)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Daniel Schmidt
|
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,45 @@
|
|
1
|
+
# kellerkind
|
2
|
+
|
3
|
+
Kellerkind is just a Ruby script that runs mongodump and tars the resulting dump.
|
4
|
+
|
5
|
+
It should be used with its cli but it's also possible to use it with its API.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
Install it as gem:
|
10
|
+
|
11
|
+
```
|
12
|
+
gem install kellerkind
|
13
|
+
```
|
14
|
+
|
15
|
+
Run from the command line:
|
16
|
+
|
17
|
+
```
|
18
|
+
kellerkind --help
|
19
|
+
```
|
20
|
+
|
21
|
+
to the arguments you could specify.
|
22
|
+
|
23
|
+
**Example**
|
24
|
+
|
25
|
+
```
|
26
|
+
kellerkind --mongo-db appDatabase --mongo-host linus.mongohq.com --mongo-port 10010 --mongo-username myUser --mongo-password myCrypticPassword --compress true --out $HOME/tmp/mongodump
|
27
|
+
```
|
28
|
+
|
29
|
+
Dumps a database hosted at MongoHQ to <code>$HOME/tmp/mongodump</code> and create a tar file of this dump.
|
30
|
+
|
31
|
+
## Contributing to kellerkind
|
32
|
+
|
33
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
34
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
35
|
+
* Fork the project.
|
36
|
+
* Start a feature/bugfix branch.
|
37
|
+
* Commit and push until you are happy with your contribution.
|
38
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
39
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
40
|
+
|
41
|
+
## Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2013 Daniel Schmidt. See LICENSE.txt for
|
44
|
+
further details.
|
45
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "kellerkind"
|
18
|
+
gem.homepage = "http://github.com/dsci/kellerkind"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Mongodb archiving tool.}
|
21
|
+
gem.description = %Q{Dumps mongodb databases and archives them.}
|
22
|
+
gem.email = "dsci@code79.net"
|
23
|
+
gem.authors = ["Daniel Schmidt"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rdoc/task'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "kellerkind #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/bin/kellerkind
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
3
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'kellerkind'
|
6
|
+
|
7
|
+
REQUIRED_ARGS = {
|
8
|
+
:mongo_db => %Q{You must specify a mongo database! },
|
9
|
+
:out => %Q{You must specify a path the dump should saved to! }
|
10
|
+
}
|
11
|
+
|
12
|
+
opts = Trollop::options do
|
13
|
+
banner <<-EOS
|
14
|
+
Mongodb archiving tool.
|
15
|
+
|
16
|
+
Dumps mongodb databases and archives them. Nothing more. Neat, isn't it?
|
17
|
+
EOS
|
18
|
+
|
19
|
+
opt :mongo_db, "mongo database to dump", :type => :string
|
20
|
+
opt :mongo_host, "mongo host to connect to", :type => :string,
|
21
|
+
:default => "localhost"
|
22
|
+
opt :mongo_username, "mongo username", :type => :string
|
23
|
+
opt :mongo_password, "mongo password", :type => :string
|
24
|
+
opt :mongo_port, "mongo server port", :type => :string,
|
25
|
+
:default => "27017"
|
26
|
+
opt :out, "path to dump to", :type => :string
|
27
|
+
opt :compress, "use gzip compression?", :type => :boolean,
|
28
|
+
:default => false
|
29
|
+
opt :remove_dump, "remove dump after compression?", :type => :boolean,
|
30
|
+
:default => true
|
31
|
+
end
|
32
|
+
|
33
|
+
REQUIRED_ARGS.each_pair do |key,value|
|
34
|
+
Trollop::die key, value unless opts[key]
|
35
|
+
end
|
36
|
+
|
37
|
+
Kellerkind::Runner.exec(opts)
|
38
|
+
|
data/kellerkind.gemspec
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "kellerkind"
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Daniel Schmidt"]
|
12
|
+
s.date = "2013-07-05"
|
13
|
+
s.description = "Dumps mongodb databases and archives them."
|
14
|
+
s.email = "dsci@code79.net"
|
15
|
+
s.executables = ["kellerkind"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.md",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/kellerkind",
|
30
|
+
"kellerkind.gemspec",
|
31
|
+
"lib/kellerkind.rb",
|
32
|
+
"lib/kellerkind/core/configuration.rb",
|
33
|
+
"lib/kellerkind/core/ext.rb",
|
34
|
+
"lib/kellerkind/core/set.rb",
|
35
|
+
"lib/kellerkind/database/mongo.rb",
|
36
|
+
"lib/kellerkind/dependencies.rb",
|
37
|
+
"lib/kellerkind/system/compress.rb",
|
38
|
+
"lib/kellerkind/system/die.rb",
|
39
|
+
"lib/kellerkind/system/lock.rb",
|
40
|
+
"lib/kellerkind/system/runner.rb",
|
41
|
+
"spec/fixtures/mongodb.js",
|
42
|
+
"spec/kellerkind/database/mongo_spec.rb",
|
43
|
+
"spec/kellerkind/system/compress_spec.rb",
|
44
|
+
"spec/kellerkind/system/lock_spec.rb",
|
45
|
+
"spec/kellerkind/tmp/.gitkeep",
|
46
|
+
"spec/kellerkind_spec.rb",
|
47
|
+
"spec/spec_helper.rb"
|
48
|
+
]
|
49
|
+
s.homepage = "http://github.com/dsci/kellerkind"
|
50
|
+
s.licenses = ["MIT"]
|
51
|
+
s.require_paths = ["lib"]
|
52
|
+
s.rubygems_version = "1.8.25"
|
53
|
+
s.summary = "Mongodb archiving tool."
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<virtus>, ["~> 0.5.5"])
|
60
|
+
s.add_runtime_dependency(%q<minitar>, ["~> 0.5.4"])
|
61
|
+
s.add_runtime_dependency(%q<trollop>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.13.0"])
|
63
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
64
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.3.5"])
|
65
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<virtus>, ["~> 0.5.5"])
|
68
|
+
s.add_dependency(%q<minitar>, ["~> 0.5.4"])
|
69
|
+
s.add_dependency(%q<trollop>, [">= 0"])
|
70
|
+
s.add_dependency(%q<rspec>, ["~> 2.13.0"])
|
71
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
72
|
+
s.add_dependency(%q<bundler>, ["~> 1.3.5"])
|
73
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<virtus>, ["~> 0.5.5"])
|
77
|
+
s.add_dependency(%q<minitar>, ["~> 0.5.4"])
|
78
|
+
s.add_dependency(%q<trollop>, [">= 0"])
|
79
|
+
s.add_dependency(%q<rspec>, ["~> 2.13.0"])
|
80
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
81
|
+
s.add_dependency(%q<bundler>, ["~> 1.3.5"])
|
82
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Kellerkind
|
2
|
+
|
3
|
+
# Public: Various methods useful for configure Kellerkind.
|
4
|
+
module Config
|
5
|
+
extend self
|
6
|
+
|
7
|
+
|
8
|
+
# Public: Gets the prefix that is use in the cli for database options.
|
9
|
+
#
|
10
|
+
# Returns a regular expression.
|
11
|
+
def db_prefix
|
12
|
+
/mongo_/
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# Public: Gets the name of the command line executable to use for
|
17
|
+
# dumping.
|
18
|
+
#
|
19
|
+
# Returns name of executable as String.
|
20
|
+
def db_dump_cmd
|
21
|
+
"mongodump"
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Public: Gets the path to the lock dir to mark process running.
|
26
|
+
# Note that just one kellerkind process is runnable.
|
27
|
+
def lock_dir
|
28
|
+
File.join(Dir.home, "tmp")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: Gets the direct path to kellerkind lock file
|
32
|
+
def lock_path
|
33
|
+
File.join(lock_dir,"Kellerkind.lock")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Internal: Gets message for action when dumping was started.
|
37
|
+
def start_dumping
|
38
|
+
%Q{Start dumping ...}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Internal: Gets message for action when a dump is about to remove.
|
42
|
+
def remove_dump
|
43
|
+
%Q{Remove raw dump. To disable that use --remove-dump false}
|
44
|
+
end
|
45
|
+
|
46
|
+
# Internal: Gets message for action when compressing was started.
|
47
|
+
def start_compressing
|
48
|
+
%Q{Start compressing of dump ... }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Internal: Gets message for action when compressing is finished.
|
52
|
+
def finished_compressing
|
53
|
+
%Q{Compressing done ...}
|
54
|
+
end
|
55
|
+
|
56
|
+
# Internal: Gets message for action when all is done.
|
57
|
+
#
|
58
|
+
# database - Name of the database from which a dump is created.
|
59
|
+
def finished_dumping(database)
|
60
|
+
%Q{ -- Dumping of #{database} done ...}
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Kellerkind
|
2
|
+
class Set
|
3
|
+
include Virtus
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def init_instance(options)
|
8
|
+
options.each_pair do |key,value|
|
9
|
+
instance_attr = key.to_s.split(Kellerkind::Config.db_prefix).last
|
10
|
+
if instance_attr.to_sym.in?(attributes.keys)
|
11
|
+
self.send("#{instance_attr}=", value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Kellerkind
|
2
|
+
|
3
|
+
# Public: Dumps a MongoDb database.
|
4
|
+
#
|
5
|
+
# For more see mongodump --help
|
6
|
+
class Mongo < Set
|
7
|
+
|
8
|
+
# MongoDb database (required)
|
9
|
+
attribute :db, String
|
10
|
+
# MongoDb host
|
11
|
+
attribute :host, String
|
12
|
+
# MongoDb user
|
13
|
+
attribute :username, String
|
14
|
+
# MongoDb user password
|
15
|
+
attribute :password, String
|
16
|
+
# MongoDb server host
|
17
|
+
attribute :port, String
|
18
|
+
# File path location for dump
|
19
|
+
attribute :out, String
|
20
|
+
|
21
|
+
def initialize(options={})
|
22
|
+
init_instance(options) unless options.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Public: Dumps the database by using a stream to the underlying
|
27
|
+
# operation system.
|
28
|
+
#
|
29
|
+
def dump_database
|
30
|
+
cmd = %Q{`which #{Kellerkind::Config.db_dump_cmd}` #{dump_argument_list}}
|
31
|
+
out = IO.popen(cmd)
|
32
|
+
out.readlines.join(" ")
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# Public: Builds an argument list for mongodump by taking only values
|
37
|
+
# existing in #attributes
|
38
|
+
#
|
39
|
+
# Returns the argument list string.
|
40
|
+
def dump_argument_list
|
41
|
+
usable_line_args = attributes.select{|k,v| not v.nil? }
|
42
|
+
return "" if usable_line_args.empty?
|
43
|
+
return usable_line_args.collect do |key,value|
|
44
|
+
"--#{key} #{value}"
|
45
|
+
end.join(" ")
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def init_instance(options)
|
51
|
+
options.each_pair do |key,value|
|
52
|
+
instance_attr = key.to_s.split(Kellerkind::Config.db_prefix).last
|
53
|
+
if instance_attr.to_sym.in?(attributes.keys)
|
54
|
+
self.send("#{instance_attr}=", value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'archive/tar/minitar'
|
3
|
+
|
4
|
+
module Kellerkind
|
5
|
+
|
6
|
+
# Public: Compresses a mongodb dump directory by using Gzip and tar.
|
7
|
+
class Compress < Set
|
8
|
+
|
9
|
+
include Archive::Tar
|
10
|
+
|
11
|
+
# Path where dump is located (parent direcotry of the dump)
|
12
|
+
attribute :path, String
|
13
|
+
# Database name which equals the dumps directory name
|
14
|
+
attribute :database_name, String
|
15
|
+
|
16
|
+
|
17
|
+
# Public: Initialises compressing of the dumps directory.
|
18
|
+
def gzip
|
19
|
+
traverse_and_gzip
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# Public: Checks if tar file exists.
|
24
|
+
#
|
25
|
+
# If tar file exists we assume compressing succeeds
|
26
|
+
#
|
27
|
+
# Returns true if file exists otherwise false.
|
28
|
+
def succeeded?
|
29
|
+
File.exists?(File.join(self.path, @actual_tar_name))
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def traverse_and_gzip
|
35
|
+
Dir.chdir(self.path) do
|
36
|
+
Find.find(self.database_name).each do |file|
|
37
|
+
if File.directory?(file)
|
38
|
+
tgz = Zlib::GzipWriter.new(db_dump_gz_file)
|
39
|
+
Minitar.pack(file, tgz)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def tarball_name
|
46
|
+
"#{self.database_name}_#{Time.now.to_i}.tar.gz"
|
47
|
+
end
|
48
|
+
|
49
|
+
def db_dump_gz_file
|
50
|
+
File.open(tar_location, 'wb')
|
51
|
+
end
|
52
|
+
|
53
|
+
def tar_location
|
54
|
+
@actual_tar_name = tarball_name
|
55
|
+
File.join(self.path, @actual_tar_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Kellerkind
|
2
|
+
module Lock
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def lock_process
|
6
|
+
unless File.exists?(Kellerkind::Config.lock_dir)
|
7
|
+
FileUtils.mkdir(Kellerkind::Config.lock_dir)
|
8
|
+
end
|
9
|
+
FileUtils.touch(Kellerkind::Config.lock_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def unlock_process
|
13
|
+
if File.exists?(Kellerkind::Config.lock_path)
|
14
|
+
FileUtils.rm(Kellerkind::Config.lock_path)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Kellerkind
|
2
|
+
class Runner
|
3
|
+
extend Die
|
4
|
+
|
5
|
+
PROCESS_LOCKED_WARNING = <<-WARNING
|
6
|
+
kellerkind.lock find! Make sure that there isn't another kellerkind process running!
|
7
|
+
WARNING
|
8
|
+
|
9
|
+
DUMP_NOT_SUCCEEDED_WARNING = <<-WARNING
|
10
|
+
No dump found. It seems dumping failed.
|
11
|
+
WARNING
|
12
|
+
|
13
|
+
def self.exec(options={})
|
14
|
+
process_locked?
|
15
|
+
lock_process
|
16
|
+
mongo = Mongo.new(options)
|
17
|
+
puts Kellerkind::Config.start_dumping
|
18
|
+
mongo.dump_database
|
19
|
+
if options[:compress]
|
20
|
+
compress = Compress.new(:path => options[:out],
|
21
|
+
:database_name =>options[:mongo_db])
|
22
|
+
if File.exists?(File.join(options[:out], options[:mongo_db]))
|
23
|
+
puts Kellerkind::Config.start_compressing
|
24
|
+
compress.gzip
|
25
|
+
if compress.succeeded?
|
26
|
+
puts Kellerkind::Config.finished_compressing
|
27
|
+
if options[:remove_dump]
|
28
|
+
puts Kellerkind::Config.remove_dump
|
29
|
+
FileUtils.rm_rf(File.join(options[:out],mongo.db))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
unlock_process
|
34
|
+
die(DUMP_NOT_SUCCEEDED_WARNING)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
unlock_process
|
39
|
+
puts Kellerkind::Config.finished_dumping(mongo.db)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.process_locked?
|
43
|
+
die(PROCESS_LOCKED_WARNING) if File.exists?(Kellerkind::Config.lock_path)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def self.lock_process
|
49
|
+
Kellerkind::Lock.lock_process
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.unlock_process
|
53
|
+
Kellerkind::Lock.unlock_process
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/kellerkind.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kellerkind::Mongo do
|
4
|
+
|
5
|
+
it{ should respond_to(:db) }
|
6
|
+
it{ should respond_to(:host) }
|
7
|
+
it{ should respond_to(:username) }
|
8
|
+
it{ should respond_to(:password) }
|
9
|
+
it{ should respond_to(:port) }
|
10
|
+
it{ should respond_to(:out) }
|
11
|
+
|
12
|
+
describe "instance methoods" do
|
13
|
+
|
14
|
+
let(:attributes) do
|
15
|
+
{
|
16
|
+
:mongo_db => "test",
|
17
|
+
:mongo_host => "localhost",
|
18
|
+
:mongo_username => "rspec_user",
|
19
|
+
:mongo_password => "no_pwd",
|
20
|
+
:mongo_port => "27017"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
it{ should respond_to(:dump_database) }
|
25
|
+
it{ should respond_to(:dump_argument_list)}
|
26
|
+
|
27
|
+
describe "#initialize" do
|
28
|
+
|
29
|
+
context "with a hash of attributes" do
|
30
|
+
|
31
|
+
context "that uses the proper prefix" do
|
32
|
+
|
33
|
+
subject{ Kellerkind::Mongo.new(attributes) }
|
34
|
+
|
35
|
+
it "then initializes the instance with the attributes values" do
|
36
|
+
subject.db.should eq attributes[:mongo_db]
|
37
|
+
subject.host.should eq attributes[:mongo_host]
|
38
|
+
subject.username.should eq attributes[:mongo_username]
|
39
|
+
subject.password.should eq attributes[:mongo_password]
|
40
|
+
subject.port.should eq attributes[:mongo_port]
|
41
|
+
|
42
|
+
subject.dump_database
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
context "that uses not the proper prefix" do
|
48
|
+
let(:inproper_attributes) do
|
49
|
+
attributes.delete(:mongo_db)
|
50
|
+
attributes[:super_database] = "testa"
|
51
|
+
attributes
|
52
|
+
end
|
53
|
+
|
54
|
+
subject{ Kellerkind::Mongo.new(inproper_attributes) }
|
55
|
+
|
56
|
+
it "then initializes the instance without these attributes" do
|
57
|
+
subject.db.should be nil
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#dump_argument_list" do
|
67
|
+
|
68
|
+
context "and arguments given" do
|
69
|
+
|
70
|
+
let(:mongo){ Kellerkind::Mongo.new(attributes) }
|
71
|
+
|
72
|
+
subject{ mongo.dump_argument_list }
|
73
|
+
|
74
|
+
context "then returns a parameter list including the instances attributes" do
|
75
|
+
|
76
|
+
it{ should match(/--db #{attributes[:mongo_db]}{1,}/) }
|
77
|
+
it{ should match(/--password #{attributes[:mongo_password]}{1,}/) }
|
78
|
+
it{ should match(/--host #{attributes[:mongo_host]}{1,}/) }
|
79
|
+
it{ should match(/--port #{attributes[:mongo_port]}{1,}/)}
|
80
|
+
it{ should match(/--username #{attributes[:mongo_username]}{1,}/)}
|
81
|
+
|
82
|
+
it{ should_not match(/--host #{attributes[:mongo_host]}{2,*}/)}
|
83
|
+
it{ should_not match(/--db #{attributes[:mongo_db]}{2,*}/) }
|
84
|
+
it{ should_not match(/--password #{attributes[:mongo_password]}{2,*}/) }
|
85
|
+
it{ should_not match(/--host #{attributes[:mongo_host]}{2,*}/) }
|
86
|
+
it{ should_not match(/--port #{attributes[:mongo_port]}{2,*}/)}
|
87
|
+
it{ should_not match(/--user_name #{attributes[:mongo_username]}{2,*}/)}
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context "and no arguments given" do
|
94
|
+
|
95
|
+
let(:mongo){ Kellerkind::Mongo.new }
|
96
|
+
|
97
|
+
subject{ mongo.dump_argument_list }
|
98
|
+
|
99
|
+
it "then returns an empty string" do
|
100
|
+
subject.should be_empty
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "#dump_database" do
|
108
|
+
let(:out_dir) do
|
109
|
+
File.expand_path(File.join(File.dirname(__FILE__),"..", "tmp"))
|
110
|
+
end
|
111
|
+
let(:dump_attributes) do
|
112
|
+
{
|
113
|
+
:mongo_db => "kellerkindTest",
|
114
|
+
:mongo_port => "27017",
|
115
|
+
:mongo_host => "localhost",
|
116
|
+
:mongo_out => out_dir
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
before do
|
121
|
+
js_path = File.expand_path(File.join(__FILE__,'..','..','fixtures'))
|
122
|
+
system("`which mongo` #{js_path}/mongodb.js")
|
123
|
+
end
|
124
|
+
|
125
|
+
after do
|
126
|
+
if File.exists?(out_dir)
|
127
|
+
FileUtils.rm_rf(out_dir)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
subject{ Kellerkind::Mongo.new(dump_attributes) }
|
132
|
+
|
133
|
+
it "dumps database content into --out" do
|
134
|
+
subject.dump_database
|
135
|
+
File.exists?("#{out_dir}/kellerkindTest").should be true
|
136
|
+
File.exists?("#{out_dir}/kellerkindTest/tests.bson").should be true
|
137
|
+
File.exists?("#{out_dir}/kellerkindTest/tests.metadata.json").should be true
|
138
|
+
File.exists?("#{out_dir}/kellerkindTest/system.indexes.bson").should be true
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Kellerkind::Compress do
|
4
|
+
|
5
|
+
it{ should respond_to(:path) }
|
6
|
+
it{ should respond_to(:database_name) }
|
7
|
+
|
8
|
+
describe "instance methods" do
|
9
|
+
let(:out_dir) do
|
10
|
+
File.expand_path(File.join(File.dirname(__FILE__),"..", "tmp"))
|
11
|
+
end
|
12
|
+
let(:attributes) do
|
13
|
+
{
|
14
|
+
:database_name => "test",
|
15
|
+
:path => out_dir
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
it{ should respond_to(:gzip) }
|
20
|
+
|
21
|
+
context "with a hash of attributes" do
|
22
|
+
subject{ Kellerkind::Compress.new(attributes) }
|
23
|
+
|
24
|
+
it "then initializes the instance with the attributes values" do
|
25
|
+
subject.database_name.should eq attributes[:database_name]
|
26
|
+
subject.path.should eq attributes[:path]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#gzip" do
|
31
|
+
let(:test_dump) do
|
32
|
+
File.join(out_dir, attributes[:database_name])
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:compress) do
|
36
|
+
Kellerkind::Compress.new(:path => out_dir, :database_name => "test")
|
37
|
+
end
|
38
|
+
|
39
|
+
before do
|
40
|
+
FileUtils.mkdir_p(test_dump)
|
41
|
+
FileUtils.touch(File.join(test_dump, "foo.txt"))
|
42
|
+
compress.gzip
|
43
|
+
end
|
44
|
+
|
45
|
+
after do
|
46
|
+
Dir["#{out_dir}/*.tar.gz"].each{ |tar| FileUtils.rm(tar) }
|
47
|
+
FileUtils.rm_rf(test_dump)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "tars and gzip the given database dump" do
|
51
|
+
Dir["#{out_dir}/#{compress.database_name}_*.tar.gz"].should have(1).item
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Locking and unlocking process" do
|
4
|
+
let(:tmp_path) do
|
5
|
+
File.expand_path(File.join(File.dirname(__FILE__),"..", "tmp"))
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:lock_file){ File.join(tmp_path,"Kellerkind.lock") }
|
9
|
+
|
10
|
+
before do
|
11
|
+
Kellerkind::Config.stub!(:lock_dir).and_return(tmp_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#lock_process" do
|
15
|
+
|
16
|
+
after do
|
17
|
+
FileUtils.rm(lock_file)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "creates a file do mark the process as locked" do
|
21
|
+
Kellerkind::Lock.lock_process
|
22
|
+
File.exists?(lock_file).should be true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#unlock_process" do
|
28
|
+
|
29
|
+
before do
|
30
|
+
FileUtils.touch(lock_file)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "removes the lock file to mark the process as runnable" do
|
34
|
+
Kellerkind::Lock.unlock_process
|
35
|
+
File.exists?(lock_file).should be false
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'kellerkind'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kellerkind
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Daniel Schmidt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: virtus
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.5.5
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.5.5
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: minitar
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.5.4
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.5.4
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: trollop
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.13.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.13.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rdoc
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '3.12'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '3.12'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bundler
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.3.5
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.3.5
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: jeweler
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.8.4
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.8.4
|
126
|
+
description: Dumps mongodb databases and archives them.
|
127
|
+
email: dsci@code79.net
|
128
|
+
executables:
|
129
|
+
- kellerkind
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files:
|
132
|
+
- LICENSE.txt
|
133
|
+
- README.md
|
134
|
+
files:
|
135
|
+
- .document
|
136
|
+
- .rspec
|
137
|
+
- Gemfile
|
138
|
+
- Gemfile.lock
|
139
|
+
- LICENSE.txt
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- VERSION
|
143
|
+
- bin/kellerkind
|
144
|
+
- kellerkind.gemspec
|
145
|
+
- lib/kellerkind.rb
|
146
|
+
- lib/kellerkind/core/configuration.rb
|
147
|
+
- lib/kellerkind/core/ext.rb
|
148
|
+
- lib/kellerkind/core/set.rb
|
149
|
+
- lib/kellerkind/database/mongo.rb
|
150
|
+
- lib/kellerkind/dependencies.rb
|
151
|
+
- lib/kellerkind/system/compress.rb
|
152
|
+
- lib/kellerkind/system/die.rb
|
153
|
+
- lib/kellerkind/system/lock.rb
|
154
|
+
- lib/kellerkind/system/runner.rb
|
155
|
+
- spec/fixtures/mongodb.js
|
156
|
+
- spec/kellerkind/database/mongo_spec.rb
|
157
|
+
- spec/kellerkind/system/compress_spec.rb
|
158
|
+
- spec/kellerkind/system/lock_spec.rb
|
159
|
+
- spec/kellerkind/tmp/.gitkeep
|
160
|
+
- spec/kellerkind_spec.rb
|
161
|
+
- spec/spec_helper.rb
|
162
|
+
homepage: http://github.com/dsci/kellerkind
|
163
|
+
licenses:
|
164
|
+
- MIT
|
165
|
+
post_install_message:
|
166
|
+
rdoc_options: []
|
167
|
+
require_paths:
|
168
|
+
- lib
|
169
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
170
|
+
none: false
|
171
|
+
requirements:
|
172
|
+
- - ! '>='
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
175
|
+
segments:
|
176
|
+
- 0
|
177
|
+
hash: 3218703124372926278
|
178
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
|
+
none: false
|
180
|
+
requirements:
|
181
|
+
- - ! '>='
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
requirements: []
|
185
|
+
rubyforge_project:
|
186
|
+
rubygems_version: 1.8.25
|
187
|
+
signing_key:
|
188
|
+
specification_version: 3
|
189
|
+
summary: Mongodb archiving tool.
|
190
|
+
test_files: []
|