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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ pkg
3
+ Gemfile.lock
4
+ test/.vagrant
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_helper'
2
+
3
+ # Change to the directory of this file.
4
+ Dir.chdir(File.expand_path("../", __FILE__))
5
+
6
+ namespace :gem do
7
+ Bundler::GemHelper.install_tasks
8
+ end
9
+
10
+ task :test do
11
+ sh 'bash test/test.sh'
12
+ end
@@ -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,13 @@
1
+ module VagrantPlugins
2
+ module MongoDb
3
+ module Errors
4
+ class MongoDbError < Vagrant::Errors::VagrantError
5
+ error_namespace("vagrant_mongodb.errors")
6
+ end
7
+
8
+ class ReplSetInitiateError < MongoDbError
9
+ error_key(:initiate)
10
+ end
11
+ end
12
+ end
13
+ 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
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module MongoDb
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ en:
2
+ vagrant_mongodb:
3
+ errors:
4
+ initiate: "Failed to initiate replica set"
5
+ actions:
6
+ replset_initiate:
7
+ initiate: "Initiating replica set '%{name}'"
@@ -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
@@ -0,0 +1,11 @@
1
+ gem build *.gemspec
2
+ vagrant plugin install vagrant-mongodb
3
+
4
+ cd test
5
+
6
+ vagrant up
7
+ sleep 30
8
+ vagrant ssh server1 -c 'mongo --eval "printjson(rs.status())"'
9
+ vagrant destroy -f
10
+
11
+ cd ..
@@ -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