vagrant-mongodb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +12 -0
- data/lib/vagrant-mongodb.rb +12 -0
- data/lib/vagrant-mongodb/actions/replset_initiate.rb +98 -0
- data/lib/vagrant-mongodb/config.rb +43 -0
- data/lib/vagrant-mongodb/errors.rb +13 -0
- data/lib/vagrant-mongodb/helpers/translator.rb +20 -0
- data/lib/vagrant-mongodb/plugin.rb +60 -0
- data/lib/vagrant-mongodb/version.rb +5 -0
- data/locales/en.yml +7 -0
- data/test/Vagrantfile +33 -0
- data/test/test.sh +11 -0
- data/vagrant-mongodb.gemspec +18 -0
- metadata +63 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Shawn Dahlen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Vagrant MongoDb
|
2
|
+
===============
|
3
|
+
`vagrant-mongodb` is a Vagrant 1.1+ plugin that supports the configuration
|
4
|
+
and initiation of a MongoDb replica set. The longer-term goal is to support
|
5
|
+
various MongoDb administrative tasks.
|
6
|
+
|
7
|
+
Status
|
8
|
+
------
|
9
|
+
The current implementation is a proof-of-concept supporting the larger
|
10
|
+
objective of using Vagrant as a cloud management interface for development
|
11
|
+
and production environments.
|
12
|
+
|
13
|
+
The plugin has been tested with Vagrant 1.1.4 and Ubuntu 12.04 guest.
|
14
|
+
|
15
|
+
Installation
|
16
|
+
------------
|
17
|
+
Install the plugin following the typical Vagrant 1.1 procedure:
|
18
|
+
|
19
|
+
vagrant plugin install vagrant-mongodb
|
20
|
+
|
21
|
+
Usage
|
22
|
+
-----
|
23
|
+
The MongoDb replica set must be configured within the project's `Vagrantfile`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
config.mongodb.replset :rs0 do |rs|
|
27
|
+
rs.member :server1, :priority => 1
|
28
|
+
rs.member :server2, :priority => 2
|
29
|
+
rs.member :server3, :priority => 1
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
The first argument to `rs.member` is the machine name defined within the
|
34
|
+
configuration. The second argument is optional taking a hash of options
|
35
|
+
for the replica set member. These options are defined within MongoDb's
|
36
|
+
[replica set configuration reference][1].
|
37
|
+
|
38
|
+
The plugin hooks into the `vagrant up` command automatically. It detects
|
39
|
+
when all members of the replica set are available before calling
|
40
|
+
`rs.initiate()`. Communication with the replica set occurs over SSH using
|
41
|
+
the `mongo` shell command.
|
42
|
+
|
43
|
+
Contribute
|
44
|
+
----------
|
45
|
+
Contributions are welcome.
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
require 'vagrant-mongodb/version'
|
3
|
+
require 'vagrant-mongodb/plugin'
|
4
|
+
require 'vagrant-mongodb/errors'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module MongoDb
|
8
|
+
def self.source_root
|
9
|
+
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module MongoDb
|
3
|
+
module Actions
|
4
|
+
class ReplSetInitiate
|
5
|
+
include Vagrant::Util::Retryable
|
6
|
+
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@config = env[:global_config].mongodb
|
10
|
+
@machine = env[:machine]
|
11
|
+
@translator = Helpers::Translator.new('actions.replset_initiate')
|
12
|
+
@logger = Log4r::Logger.new('vagrant_mongodb::actions::replset_initiate')
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
@app.call(env)
|
17
|
+
|
18
|
+
# check if the current machine is a member of a replica set
|
19
|
+
@logger.info "Checking if '#{@machine.name}' is part of a replica set..."
|
20
|
+
rs = get_replset(@machine.name) if @config
|
21
|
+
return if !rs
|
22
|
+
|
23
|
+
# ensure all members are available before initiating replica set
|
24
|
+
if all_members_available?(rs)
|
25
|
+
env[:ui].info @translator.t('initiate', { :name => rs.name })
|
26
|
+
command = "mongo --eval 'printjson(rs.initiate(#{generate_json(rs)}))'"
|
27
|
+
env[:machine].communicate.execute(command) do |type, data|
|
28
|
+
raise Errors::ReplSetInitiateError if data =~ /"ok" : 0/
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# return the replset containing the machine name
|
36
|
+
def get_replset(name)
|
37
|
+
@config.replsets.find do |rs|
|
38
|
+
rs.members.find do |member|
|
39
|
+
member[:host] == name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# check if the given machine has mongod running
|
45
|
+
def member_available?(machine)
|
46
|
+
@logger.info "Checking if '#{machine.name}' mongod is available..."
|
47
|
+
return false if !machine.communicate.ready?
|
48
|
+
|
49
|
+
# try executing the mongo command on the machine several times
|
50
|
+
# to allow for a process to start after provisioning
|
51
|
+
command = 'mongo --eval "db.runCommand({ ping: 1 })"'
|
52
|
+
retryable(:tries => 3, :sleep => 10) do
|
53
|
+
machine.communicate.execute(command)
|
54
|
+
@logger.info "'#{machine.name}' mongod is available..."
|
55
|
+
end
|
56
|
+
true
|
57
|
+
rescue
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
# check if all members of the replica set have mongod running
|
62
|
+
def all_members_available?(rs)
|
63
|
+
global_env = @machine.env
|
64
|
+
rs.members.each do |member|
|
65
|
+
machine = global_env.machine(member[:host], @machine.provider_name)
|
66
|
+
return false if !member_available?(machine)
|
67
|
+
end
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
# generate replica set JSON document replacing host name with ip
|
72
|
+
def generate_json(rs)
|
73
|
+
global_env = @machine.env
|
74
|
+
members = rs.members.dup
|
75
|
+
members.each do |member|
|
76
|
+
machine = global_env.machine(member[:host], @machine.provider_name)
|
77
|
+
member[:host] = get_ip_address(machine)
|
78
|
+
@logger.info "Using ip address '#{member[:host]}' for '#{@machine.name}'..."
|
79
|
+
end
|
80
|
+
|
81
|
+
{ :_id => rs.name, :members => members }.to_json
|
82
|
+
end
|
83
|
+
|
84
|
+
# return the ip address of the given machine
|
85
|
+
def get_ip_address(machine)
|
86
|
+
ip = nil
|
87
|
+
machine.config.vm.networks.each do |network|
|
88
|
+
key, options = network[0], network[1]
|
89
|
+
ip = options[:ip] if key == :private_network
|
90
|
+
next if ip
|
91
|
+
end
|
92
|
+
|
93
|
+
ip || machine.ssh_info[:host]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module MongoDb
|
3
|
+
class Config < Vagrant.plugin('2', :config)
|
4
|
+
attr_reader :replsets
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@replsets = []
|
8
|
+
end
|
9
|
+
|
10
|
+
# Override default merge behavior
|
11
|
+
# TODO look into merge strategy
|
12
|
+
def merge(other)
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate(machine)
|
17
|
+
# TODO check that member names have a matching vm definition
|
18
|
+
# TODO check that each replica set has 3+ members
|
19
|
+
# TODO warn if replica set has even number of members
|
20
|
+
end
|
21
|
+
|
22
|
+
def replset(name, &block)
|
23
|
+
rs = ReplSet.new(name)
|
24
|
+
block.call(rs)
|
25
|
+
@replsets << rs
|
26
|
+
end
|
27
|
+
|
28
|
+
class ReplSet
|
29
|
+
attr_reader :name
|
30
|
+
attr_reader :members
|
31
|
+
|
32
|
+
def initialize(name)
|
33
|
+
@name = name
|
34
|
+
@members = []
|
35
|
+
end
|
36
|
+
|
37
|
+
def member(name, options = {})
|
38
|
+
@members << options.merge({ :_id => @members.size, :host => name})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module MongoDb
|
3
|
+
module Helpers
|
4
|
+
class Translator
|
5
|
+
def self.plugin_namespace=(val)
|
6
|
+
@@plugin_namespace = val
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(namespace)
|
10
|
+
@namespace = namespace
|
11
|
+
end
|
12
|
+
|
13
|
+
def t(keys, opts = {})
|
14
|
+
value = I18n.t("#{@@plugin_namespace}.#{@namespace}.#{keys}", opts)
|
15
|
+
opts[:progress] == false ? value : value + "..."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'vagrant-mongodb/helpers/translator'
|
2
|
+
require 'vagrant-mongodb/actions/replset_initiate'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module MongoDb
|
6
|
+
class Plugin < Vagrant.plugin('2')
|
7
|
+
name 'MongoDb'
|
8
|
+
description <<-DESC
|
9
|
+
This plugin manages a MongoDb replica set.
|
10
|
+
DESC
|
11
|
+
|
12
|
+
config(:mongodb) do
|
13
|
+
require_relative 'config'
|
14
|
+
Config
|
15
|
+
end
|
16
|
+
|
17
|
+
# initiate replica set after machine provisioning
|
18
|
+
action_hook(:replset_initiate, :machine_action_up) do |hook|
|
19
|
+
setup_logging
|
20
|
+
setup_i18n
|
21
|
+
hook.before(Vagrant::Action::Builtin::Provision, Actions::ReplSetInitiate)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.setup_i18n
|
25
|
+
I18n.load_path << File.expand_path(
|
26
|
+
'locales/en.yml',
|
27
|
+
MongoDb.source_root)
|
28
|
+
I18n.reload!
|
29
|
+
|
30
|
+
Helpers::Translator.plugin_namespace = 'vagrant_mongodb'
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.setup_logging
|
34
|
+
level = nil
|
35
|
+
begin
|
36
|
+
level = Log4r.const_get(ENV['VAGRANT_LOG'].upcase)
|
37
|
+
rescue NameError
|
38
|
+
# This means that the logging constant wasn't found,
|
39
|
+
# which is fine. We just keep `level` as `nil`. But
|
40
|
+
# we tell the user.
|
41
|
+
level = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# Some constants, such as "true" resolve to booleans, so the
|
45
|
+
# above error checking doesn't catch it. This will check to make
|
46
|
+
# sure that the log level is an integer, as Log4r requires.
|
47
|
+
level = nil if !level.is_a?(Integer)
|
48
|
+
|
49
|
+
# Set the logging level on all "vagrant" namespaced
|
50
|
+
# logs as long as we have a valid level.
|
51
|
+
if level
|
52
|
+
logger = Log4r::Logger.new('vagrant_mongodb')
|
53
|
+
logger.outputters = Log4r::Outputter.stderr
|
54
|
+
logger.level = level
|
55
|
+
logger = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/locales/en.yml
ADDED
data/test/Vagrantfile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant.configure('2') do |config|
|
5
|
+
config.vm.box = 'precise64'
|
6
|
+
config.vm.box_url = 'http://files.vagrantup.com/precise64.box'
|
7
|
+
|
8
|
+
config.mongodb.replset :rs0 do |rs|
|
9
|
+
rs.member :server1, :priority => 1
|
10
|
+
rs.member :server2, :priority => 2
|
11
|
+
rs.member :server3, :priority => 1
|
12
|
+
end
|
13
|
+
|
14
|
+
script = <<-SCRIPT
|
15
|
+
apt-get -y install mongodb
|
16
|
+
echo 'replSet=rs0' >> /etc/mongodb.conf
|
17
|
+
sed -in '/^bind_ip/d' /etc/mongodb.conf
|
18
|
+
service mongodb restart
|
19
|
+
SCRIPT
|
20
|
+
config.vm.provision :shell, :inline => script
|
21
|
+
|
22
|
+
config.vm.define :server1 do |server|
|
23
|
+
server.vm.network :private_network, :ip => '10.0.5.2'
|
24
|
+
end
|
25
|
+
|
26
|
+
config.vm.define :server2 do |server|
|
27
|
+
server.vm.network :private_network, :ip => '10.0.5.3'
|
28
|
+
end
|
29
|
+
|
30
|
+
config.vm.define :server3 do |server|
|
31
|
+
server.vm.network :private_network, :ip => '10.0.5.4'
|
32
|
+
end
|
33
|
+
end
|
data/test/test.sh
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vagrant-mongodb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'vagrant-mongodb'
|
8
|
+
gem.version = VagrantPlugins::MongoDb::VERSION
|
9
|
+
gem.authors = ['Shawn Dahlen']
|
10
|
+
gem.email = ['shawn@dahlen.me']
|
11
|
+
gem.description = %q{A Vagrant plugin that manages a MongoDb replicaset}
|
12
|
+
gem.homepage = 'https://github.com/smdahlen/vagrant-mongodb'
|
13
|
+
gem.summary = gem.description
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-mongodb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Shawn Dahlen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A Vagrant plugin that manages a MongoDb replicaset
|
15
|
+
email:
|
16
|
+
- shawn@dahlen.me
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/vagrant-mongodb.rb
|
27
|
+
- lib/vagrant-mongodb/actions/replset_initiate.rb
|
28
|
+
- lib/vagrant-mongodb/config.rb
|
29
|
+
- lib/vagrant-mongodb/errors.rb
|
30
|
+
- lib/vagrant-mongodb/helpers/translator.rb
|
31
|
+
- lib/vagrant-mongodb/plugin.rb
|
32
|
+
- lib/vagrant-mongodb/version.rb
|
33
|
+
- locales/en.yml
|
34
|
+
- test/Vagrantfile
|
35
|
+
- test/test.sh
|
36
|
+
- vagrant-mongodb.gemspec
|
37
|
+
homepage: https://github.com/smdahlen/vagrant-mongodb
|
38
|
+
licenses: []
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.23
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: A Vagrant plugin that manages a MongoDb replicaset
|
61
|
+
test_files:
|
62
|
+
- test/Vagrantfile
|
63
|
+
- test/test.sh
|