mongo3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. data/.bnignore +3 -0
  2. data/.bnsignore +16 -0
  3. data/.gitignore +1 -0
  4. data/HISTORY +2 -0
  5. data/README.rdoc +78 -0
  6. data/Rakefile +31 -0
  7. data/bin/mongo3 +29 -0
  8. data/config/mongo3.yml +33 -0
  9. data/lib/controllers/collections.rb +7 -0
  10. data/lib/controllers/databases.rb +7 -0
  11. data/lib/controllers/explore.rb +46 -0
  12. data/lib/helpers/crumb_helper.rb +46 -0
  13. data/lib/helpers/main_helper.rb +43 -0
  14. data/lib/main.rb +41 -0
  15. data/lib/mongo3/connection.rb +191 -0
  16. data/lib/mongo3/node.rb +80 -0
  17. data/lib/mongo3.rb +57 -0
  18. data/lib/public/images/c292199_a.jpg +0 -0
  19. data/lib/public/images/close.png +0 -0
  20. data/lib/public/images/close.psd +0 -0
  21. data/lib/public/images/cluster.png +0 -0
  22. data/lib/public/images/cluster.psd +0 -0
  23. data/lib/public/images/db.jpg +0 -0
  24. data/lib/public/images/db.png +0 -0
  25. data/lib/public/images/db.psd +0 -0
  26. data/lib/public/images/delete.png +0 -0
  27. data/lib/public/images/header.png +0 -0
  28. data/lib/public/images/header.psd +0 -0
  29. data/lib/public/images/li_select.png +0 -0
  30. data/lib/public/images/li_select.psd +0 -0
  31. data/lib/public/images/lock.png +0 -0
  32. data/lib/public/images/lock.psd +0 -0
  33. data/lib/public/images/mongo.png +0 -0
  34. data/lib/public/images/mongo.psd +0 -0
  35. data/lib/public/images/mongo3.png +0 -0
  36. data/lib/public/images/mongo3.psd +0 -0
  37. data/lib/public/images/mongo3_db.png +0 -0
  38. data/lib/public/images/mongo3_db.psd +0 -0
  39. data/lib/public/images/mongo_10.psd +0 -0
  40. data/lib/public/images/mongo_db.jpg +0 -0
  41. data/lib/public/images/mongo_db.png +0 -0
  42. data/lib/public/images/mongo_db.psd +0 -0
  43. data/lib/public/images/mongo_db_1.jpg +0 -0
  44. data/lib/public/images/mongo_db_2 +0 -0
  45. data/lib/public/images/mongo_db_4 +0 -0
  46. data/lib/public/images/monkey.jpg +0 -0
  47. data/lib/public/images/monkey.png +0 -0
  48. data/lib/public/images/monkey.psd +0 -0
  49. data/lib/public/images/monkey_1.jpg +8 -0
  50. data/lib/public/images/monkey_10.jpg +8 -0
  51. data/lib/public/javascripts/Jit/Examples/Hypertree/example1.html +57 -0
  52. data/lib/public/javascripts/Jit/Examples/Hypertree/example1.js +427 -0
  53. data/lib/public/javascripts/Jit/Examples/Hypertree/example2.html +58 -0
  54. data/lib/public/javascripts/Jit/Examples/Hypertree/example2.js +310 -0
  55. data/lib/public/javascripts/Jit/Examples/Hypertree/example3.html +199 -0
  56. data/lib/public/javascripts/Jit/Examples/Hypertree/example3.js +615 -0
  57. data/lib/public/javascripts/Jit/Examples/Other/example1.html +58 -0
  58. data/lib/public/javascripts/Jit/Examples/Other/example1.js +566 -0
  59. data/lib/public/javascripts/Jit/Examples/Other/example2.html +58 -0
  60. data/lib/public/javascripts/Jit/Examples/Other/example2.js +304 -0
  61. data/lib/public/javascripts/Jit/Examples/Other/example3.html +58 -0
  62. data/lib/public/javascripts/Jit/Examples/Other/example3.js +304 -0
  63. data/lib/public/javascripts/Jit/Examples/RGraph/example1.html +57 -0
  64. data/lib/public/javascripts/Jit/Examples/RGraph/example1.js +475 -0
  65. data/lib/public/javascripts/Jit/Examples/RGraph/example2.html +58 -0
  66. data/lib/public/javascripts/Jit/Examples/RGraph/example2.js +356 -0
  67. data/lib/public/javascripts/Jit/Examples/RGraph/example3.html +199 -0
  68. data/lib/public/javascripts/Jit/Examples/RGraph/example3.js +622 -0
  69. data/lib/public/javascripts/Jit/Examples/Spacetree/example1.html +91 -0
  70. data/lib/public/javascripts/Jit/Examples/Spacetree/example1.js +890 -0
  71. data/lib/public/javascripts/Jit/Examples/Spacetree/example2.html +90 -0
  72. data/lib/public/javascripts/Jit/Examples/Spacetree/example2.js +213 -0
  73. data/lib/public/javascripts/Jit/Examples/Spacetree/example3.html +75 -0
  74. data/lib/public/javascripts/Jit/Examples/Spacetree/example3.js +863 -0
  75. data/lib/public/javascripts/Jit/Examples/Treemap/example1.html +56 -0
  76. data/lib/public/javascripts/Jit/Examples/Treemap/example1.js +95 -0
  77. data/lib/public/javascripts/Jit/Examples/Treemap/example2.html +61 -0
  78. data/lib/public/javascripts/Jit/Examples/Treemap/example2.js +750 -0
  79. data/lib/public/javascripts/Jit/Examples/Treemap/example3.html +62 -0
  80. data/lib/public/javascripts/Jit/Examples/Treemap/example3.js +775 -0
  81. data/lib/public/javascripts/Jit/Examples/css/Hypertree.css +0 -0
  82. data/lib/public/javascripts/Jit/Examples/css/Other.css +8 -0
  83. data/lib/public/javascripts/Jit/Examples/css/RGraph.css +0 -0
  84. data/lib/public/javascripts/Jit/Examples/css/Spacetree.css +0 -0
  85. data/lib/public/javascripts/Jit/Examples/css/Treemap.css +78 -0
  86. data/lib/public/javascripts/Jit/Examples/css/base.css +106 -0
  87. data/lib/public/javascripts/Jit/Examples/css/col1.png +0 -0
  88. data/lib/public/javascripts/Jit/Examples/css/col2.png +0 -0
  89. data/lib/public/javascripts/Jit/Examples/css/gradient.png +0 -0
  90. data/lib/public/javascripts/Jit/Extras/excanvas.js +35 -0
  91. data/lib/public/javascripts/Jit/jit-yc.js +1 -0
  92. data/lib/public/javascripts/Jit/jit.js +9052 -0
  93. data/lib/public/javascripts/Jit-1.1.3.zip +0 -0
  94. data/lib/public/javascripts/application.js +28 -0
  95. data/lib/public/javascripts/jit.min.js +1 -0
  96. data/lib/public/javascripts/jquery.tools.min.js +38 -0
  97. data/lib/public/javascripts/jquery_min.js +19 -0
  98. data/lib/public/javascripts/jquery_ui_min.js +298 -0
  99. data/lib/public/stylesheets/mongo3.css +275 -0
  100. data/lib/utils.rb +3 -0
  101. data/lib/views/_cltn_info.erb +95 -0
  102. data/lib/views/_collection.erb +5 -0
  103. data/lib/views/_crumbs.erb +13 -0
  104. data/lib/views/_dump_array.erb +5 -0
  105. data/lib/views/_dump_hash.erb +14 -0
  106. data/lib/views/_info.erb +15 -0
  107. data/lib/views/center_js.erb +3 -0
  108. data/lib/views/cltn_show.erb +1 -0
  109. data/lib/views/collection.erb +44 -0
  110. data/lib/views/database.erb +37 -0
  111. data/lib/views/db_show.erb +1 -0
  112. data/lib/views/explore.erb +250 -0
  113. data/lib/views/landscape.erb +45 -0
  114. data/lib/views/layout.erb +28 -0
  115. data/lib/views/more_data_js.erb +3 -0
  116. data/lib/views/show_cltn.erb +1 -0
  117. data/lib/views/update_crumb_js.erb +1 -0
  118. data/spec/mongo3/node_spec.rb +84 -0
  119. data/spec/spec_helper.rb +8 -0
  120. data/tasks/bones.rake +20 -0
  121. data/tasks/gem.rake +201 -0
  122. data/tasks/git.rake +40 -0
  123. data/tasks/notes.rake +27 -0
  124. data/tasks/post_load.rake +32 -0
  125. data/tasks/rdoc.rake +56 -0
  126. data/tasks/rubyforge.rake +55 -0
  127. data/tasks/setup.rb +292 -0
  128. data/tasks/spec.rake +54 -0
  129. data/tasks/svn.rake +47 -0
  130. data/tasks/test.rake +40 -0
  131. data/tasks/zentest.rake +36 -0
  132. metadata +213 -0
data/.bnignore ADDED
@@ -0,0 +1,3 @@
1
+ *.log
2
+ *.psd
3
+ .git
data/.bnsignore ADDED
@@ -0,0 +1,16 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # PROJ.ignore_file = '.gitignore'
8
+ #
9
+ # For a project with a C extension, the following would be a good set of
10
+ # exclude patterns (uncomment them if you want to use them):
11
+ # *.[oa]
12
+ # *~
13
+ announcement.txt
14
+ coverage
15
+ doc
16
+ pkg
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.psd
data/HISTORY ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.1 - Initial Drop
2
+ not much there yet...
data/README.rdoc ADDED
@@ -0,0 +1,78 @@
1
+ == Mongo3
2
+
3
+ Rule your mongoDB clusters!
4
+ A Sinatra based admin console for mongoDB
5
+
6
+ == DESCRIPTION:
7
+
8
+ Mongo3 allows you to manage your mongoDB clusters using a web based admin console.
9
+ The console provides for getting an overview of your mongo landscape and drilldown to
10
+ see various information about your databases. You will be able to manage your clusters
11
+ by performing common database admin tasks directly from the web console.
12
+
13
+ The initial release of Mongo3 will be a read only shallow mode. Further development
14
+ still needs to take place to build up the functionality from the existing code base.
15
+
16
+ == PROJECT INFORMATION
17
+
18
+ * Developer: Fernand Galiana
19
+ * Site: http://mongo3.com
20
+ * Twitter: http://twitter.com/mongo_3
21
+ * Forum: http://groups.google.com/group/mongo3
22
+
23
+ == FEATURES:
24
+
25
+ * Easily administer your mongo cluster information
26
+ * Get a real time snapshot of what your configuration looks like
27
+ * Drill down on clusters, databases, collections and indexes
28
+ * Manage all mongo artifacts from a single web interface
29
+
30
+ == ROAD MAP:
31
+
32
+ * Provide support for db authentication
33
+ * Ability to drilldown in collections and query for content
34
+ * CRUD on dbs, collections, indexes, users
35
+ * Support for managing shards and replication
36
+
37
+ == INSTALL:
38
+
39
+ sudo gem install mongo3
40
+
41
+ == USAGE:
42
+
43
+ === Configure It!
44
+
45
+ You will need to give mongo3 some information about your mongo configuration.
46
+ In order to do so create a .mongo3 directory in your home directory and create
47
+ a file landscape.yml. You will need to specify the envs, host and ports specific
48
+ to your configuration, but here is a sample.
49
+
50
+ landscape.yml
51
+ development:
52
+ host: localhost
53
+ port: 27017
54
+
55
+ beta:
56
+ host: beta_host_name
57
+ port: 27017
58
+
59
+ === Launch It!
60
+
61
+ Launch it. Fires up sinatra and opens up the console
62
+ > mongo3
63
+
64
+ == LICENSE:
65
+
66
+ Copyright 2009-2010 LiquidRail LLC
67
+
68
+ Licensed under the Apache License, Version 2.0 (the "License");
69
+ you may not use this file except in compliance with the License.
70
+ You may obtain a copy of the License at
71
+
72
+ http://www.apache.org/licenses/LICENSE-2.0
73
+
74
+ Unless required by applicable law or agreed to in writing, software
75
+ distributed under the License is distributed on an "AS IS" BASIS,
76
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77
+ See the License for the specific language governing permissions and
78
+ limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ begin
6
+ require 'bones'
7
+ Bones.setup
8
+ rescue LoadError
9
+ begin
10
+ load 'tasks/setup.rb'
11
+ rescue LoadError
12
+ raise RuntimeError, '### please install the "bones" gem ###'
13
+ end
14
+ end
15
+
16
+ ensure_in_path 'lib'
17
+ require 'mongo3'
18
+
19
+ task :default => 'spec:run'
20
+
21
+ PROJ.name = 'mongo3'
22
+ PROJ.authors = 'Fernand Galiana'
23
+ PROJ.email = 'fernand.galiana@gmail.com'
24
+ PROJ.url = 'http://www.mongo3.com'
25
+ PROJ.version = Mongo3::VERSION
26
+ PROJ.ruby_opts = %w[-W0]
27
+ PROJ.readme = 'README.rdoc'
28
+ PROJ.rcov.opts = ["--sort", "coverage", "-T"]
29
+ PROJ.ignore_file = "*.log"
30
+ PROJ.spec.opts << '--color'
31
+ PROJ.rdoc.include = %w[.rb]
data/bin/mongo3 ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'sinatra'
4
+ require File.expand_path( File.join(File.dirname(__FILE__), %w[.. lib mongo3]))
5
+ require File.join(File.dirname(__FILE__), %w[.. lib main.rb])
6
+
7
+ def open(path)
8
+ case RUBY_PLATFORM
9
+ when /darwin/
10
+ system 'open', path
11
+ when /mswin(?!ce)|mingw|cygwin|bccwin/
12
+ system 'start', path
13
+ else
14
+ system 'firefox', path
15
+ end
16
+ end
17
+
18
+ Thread.new do
19
+ puts "\n"*2
20
+ puts ">>> Waiting for Franky to warm up..."
21
+ puts "\n"*2
22
+ sleep( 3 )
23
+ puts "\n"*2
24
+ puts "\n\n >>> Opening console..."
25
+ puts "\n"*2
26
+ open( "http://localhost:6666/explore" )
27
+ end
28
+
29
+ Sinatra::Application.run! :port => 6666
data/config/mongo3.yml ADDED
@@ -0,0 +1,33 @@
1
+ development:
2
+ :host: localhost
3
+ :port: 27017
4
+
5
+ beta:
6
+ :host: dev8
7
+ :port: 27018
8
+ :user: "blee"
9
+ :password: "fred"
10
+
11
+ # production:
12
+ # :host: dev8
13
+ # :port: 27018
14
+ # :user: "blee"
15
+ # :password: "fred"
16
+ #
17
+ # serv1:
18
+ # :host: dev8
19
+ # :port: 27018
20
+ # :user: "blee"
21
+ # :password: "fred"
22
+ #
23
+ # serv2:
24
+ # :host: dev8
25
+ # :port: 27018
26
+ # :user: "blee"
27
+ # :password: "fred"
28
+ #
29
+ # serv3:
30
+ # :host: dev8
31
+ # :port: 27018
32
+ # :user: "blee"
33
+ # :password: "fred"
@@ -0,0 +1,7 @@
1
+ module Collections
2
+
3
+ get "/cltns" do
4
+ puts "Cltns"
5
+ end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ module Databases
2
+
3
+ get "/dbs" do
4
+ puts "Dbs"
5
+ end
6
+
7
+ end
@@ -0,0 +1,46 @@
1
+ module Explore
2
+
3
+ # -----------------------------------------------------------------------------
4
+ get '/explore' do
5
+ reset_crumbs!
6
+ @root = options.connection.build_tree
7
+ erb :explore
8
+ end
9
+
10
+ # -----------------------------------------------------------------------------
11
+ get '/explore/show/:path/:crumbs' do
12
+ path = params[:path]
13
+ crumbs = params[:crumbs]
14
+
15
+ @info = options.connection.show( path, crumbs )
16
+
17
+ partial :info
18
+ end
19
+
20
+ # -----------------------------------------------------------------------------
21
+ get '/explore/more_data/:path/:crumbs/*' do
22
+ path = params[:path]
23
+ crumbs = params[:crumbs]
24
+
25
+ crumbs_from_path( path, crumbs )
26
+
27
+ @sub_tree = options.connection.build_sub_tree( path, crumbs )
28
+ @node_id = @sub_tree.first[:id]
29
+
30
+ erb :more_data_js, :layout => false
31
+ end
32
+
33
+ # -----------------------------------------------------------------------------
34
+ get '/explore/update_crumb/:path/:crumbs' do
35
+ crumbs_from_path( params[:path], params[:crumbs] )
36
+ erb :update_crumb_js, :layout => false
37
+ end
38
+
39
+ # -----------------------------------------------------------------------------
40
+ get '/explore/center/:node_id' do
41
+ @node_id = params[:node_id]
42
+ pop_crumb!( @node_id )
43
+ erb :center_js, :layout => false
44
+ end
45
+
46
+ end
@@ -0,0 +1,46 @@
1
+ module CrumbHelper
2
+
3
+ helpers do
4
+ def crumbs_from_path( path, crumbs )
5
+ crumb_tokens = crumbs.split( "|" )
6
+ path_tokens = path.split( "|" )
7
+
8
+ @crumbs = []
9
+ count = 0
10
+ crumb_tokens.each do |crumb|
11
+ @crumbs << [crumb, "/explore/center/#{path_tokens[count]}"]
12
+ count += 1
13
+ end
14
+ session[:crumbs] = @crumbs
15
+ end
16
+
17
+ def pop_crumb!( node_id )
18
+ level = 0
19
+ range = nil
20
+ path = "/explore/center/#{node_id}"
21
+ @crumbs.each do |pair|
22
+ if pair.last == path
23
+ range = level
24
+ break
25
+ end
26
+ level += 1
27
+ end
28
+ @crumbs = ( range > 0 ? @crumbs[0..range] : [@crumbs[0]] )
29
+ session[:crumbs] = @crumbs
30
+ end
31
+
32
+ def reset_crumbs!
33
+ @crumbs = [ ["home", '/explore/center/home'] ]
34
+ session[:crumbs] = @crumbs
35
+ end
36
+
37
+ def add_crumb( title, url )
38
+ titles = @crumbs.map{ |p| p.first }
39
+ unless titles.include?( title )
40
+ @crumbs.pop if @crumbs.size == 3
41
+ @crumbs << [title, url]
42
+ session[:crumbs] = @crumbs
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ module MainHelper
2
+
3
+ JS_ESCAPE_MAP =
4
+ {
5
+ '\\' => '\\\\',
6
+ '</' => '<\/',
7
+ "\r\n" => '\n',
8
+ "\n" => '\n',
9
+ "\r" => '\n',
10
+ '"' => '\\"',
11
+ "'" => "\\'"
12
+ }
13
+
14
+ helpers do
15
+
16
+ def display_info( info )
17
+ return info if info.is_a?( String )
18
+ if info.is_a?( Hash )
19
+ @info = info
20
+ partial :dump_hash
21
+ elsif info.is_a?( Array )
22
+ @info = info
23
+ partial :dump_array
24
+ else
25
+ info
26
+ end
27
+ end
28
+
29
+ def partial( page, options={} )
30
+ erb "_#{page}".to_sym, options.merge!( :layout => false )
31
+ end
32
+
33
+ def escape_javascript(javascript)
34
+ if javascript
35
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
36
+ else
37
+ ''
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
data/lib/main.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'forwardable'
4
+ require File.join( File.dirname(__FILE__), 'mongo3.rb' )
5
+ require 'mongo'
6
+
7
+ set :public, File.join( File.dirname(__FILE__), %w[public] )
8
+ set :views , File.join( File.dirname(__FILE__), %w[views] )
9
+
10
+ # -----------------------------------------------------------------------------
11
+ # Configuration
12
+ configure do
13
+ Mongo3.load_all_libs_relative_to(__FILE__, 'helpers' )
14
+ Mongo3.load_all_libs_relative_to(__FILE__, 'controllers' )
15
+
16
+ set :sessions , true
17
+ set :connection, Mongo3::Connection.new( File.join( ENV['HOME'], %w[.mongo3 landscape.yml] ) )
18
+ end
19
+
20
+ # -----------------------------------------------------------------------------
21
+ # Before filters
22
+ before do
23
+ unless request.path =~ /\.[css gif png js]/
24
+ @crumbs = session[:crumbs]
25
+ unless @crumbs
26
+ @crumbs = [ ['HOME', '/center'] ]
27
+ session[:crumbs] = @crumbs
28
+ end
29
+ end
30
+ end
31
+
32
+ # =============================================================================
33
+ # Helpers
34
+ helpers do
35
+
36
+ # Convert size to mb
37
+ def to_mb( val )
38
+ return val if val < 1_000_000
39
+ "#{val/1_000_000}Mb"
40
+ end
41
+ end
@@ -0,0 +1,191 @@
1
+ module Mongo3
2
+ class Connection
3
+
4
+ def initialize( config_file )
5
+ @config_file = config_file
6
+ end
7
+
8
+ # Connects to mongo given an environment
9
+ # BOZO !! Auth...
10
+ # TODO - Need to close out connection via block
11
+ def connect_for( env, &block )
12
+ info = landscape[env]
13
+ puts ">>> Connecting for #{env} -- #{info[:host]}-#{info[:port]}"
14
+ con = Mongo::Connection.new( info[:host], info[:port] )
15
+ yield con
16
+ con.close()
17
+ end
18
+
19
+ def show( path, crumbs )
20
+ path_tokens = path.split( "|" )
21
+ crumb_tokens = crumbs.split( "|" )
22
+ info = OrderedHash.new
23
+ env = path_tokens[1]
24
+
25
+ if path_tokens.size == 2
26
+ connect_for( env ) do |con|
27
+ info[:name] = env
28
+ info[:host] = con.host
29
+ info[:port] = con.port
30
+ info[:databases] = OrderedHash.new
31
+ con.database_info.sort { |a,b| b[1] <=> a[1] }.each { |e| info[:databases][e[0]] = to_mb( e[1] ) }
32
+ info[:server] = con.server_info
33
+ end
34
+ elsif path_tokens.size == 3
35
+ db_name = crumb_tokens.pop
36
+ connect_for( env ) do |con|
37
+ db = con.db( db_name )
38
+ info[:size] = to_mb( con.database_info[db_name] )
39
+ info[:node] = db.nodes
40
+ info[:collections] = db.collection_names.size
41
+ info[:error] = db.error
42
+ info[:last_status] = db.last_status
43
+ end
44
+ elsif path_tokens.size == 4
45
+ cltn_name = crumb_tokens.pop
46
+ db_name = crumb_tokens.pop
47
+ connect_for( env ) do |con|
48
+ db = con.db( db_name )
49
+ cltn = db[cltn_name]
50
+ info[:size] = cltn.count
51
+
52
+ indexes = db.index_information( cltn_name )
53
+ info[:indexes] = format_indexes( db.index_information( cltn_name ) ) if indexes and !indexes.empty?
54
+ end
55
+ end
56
+
57
+ info
58
+ end
59
+
60
+ def format_indexes( indexes )
61
+ formatted = {}
62
+ indexes.each_pair do |key, values|
63
+ buff = []
64
+ values.each do |pair|
65
+ buff << "#{pair.first} [#{pair.last}]"
66
+ end
67
+ formatted[key] = buff
68
+ end
69
+ formatted
70
+ end
71
+
72
+ # Fetch the environment landscape from the config file
73
+ def landscape
74
+ config
75
+ end
76
+
77
+ # db request occurs within dist 2
78
+ def db_request?( path )
79
+ path.size == 2
80
+ end
81
+
82
+ # cltn request occurs within dist 3
83
+ def cltn_request?( path )
84
+ path.size == 3
85
+ end
86
+
87
+ # Build environment tree
88
+ def build_tree
89
+ root = Node.new( "home", "home", :path => 'home', :crumbs => 'home' )
90
+
91
+ # iterate thru envs
92
+ id = 1
93
+ config.each_pair do |env, info|
94
+ node = Node.new( env, env, :dyna => true )
95
+ root << node
96
+ id += 1
97
+ end
98
+ root
99
+ end
100
+
101
+ # Build an appropriate subtree based on requested item
102
+ def build_sub_tree( path, crumbs )
103
+ path_tokens = path.split( "|" )
104
+ crumb_tokens = crumbs.split( "|" )
105
+ parent_id = path_tokens.last
106
+ db_name = crumb_tokens.last
107
+
108
+ if db_request?( path_tokens )
109
+ sub_tree = build_db_tree( parent_id, db_name )
110
+ else
111
+ env = crumb_tokens[1]
112
+ sub_tree = build_cltn_tree( parent_id, env, db_name )
113
+ end
114
+ sub_tree.to_adjacencies
115
+ end
116
+
117
+
118
+ # Connects to host and spews out all available dbs
119
+ # BOZO !! Need to deal with Auth?
120
+ def build_db_tree( parent_id, env )
121
+ sub_root = nil
122
+ connect_for( env ) do |con|
123
+ root = Node.new( "home", "home" )
124
+ sub_root = Node.new( parent_id, env )
125
+
126
+ root << sub_root
127
+
128
+ count = 0
129
+ data = { :dyna => true }
130
+ # excludes = %w[admin local]
131
+ con.database_names.each do |db_name|
132
+ # next if excludes.include?( db_name )
133
+ db = con.db( db_name, :strict => true )
134
+ cltns = db.collection_names.size
135
+ node = Node.new( "#{env}_#{count}", "#{db_name}(#{cltns})", data.clone )
136
+ sub_root << node
137
+ count += 1
138
+ end
139
+ end
140
+ sub_root
141
+ end
142
+
143
+ # Show collections
144
+ def build_cltn_tree( parent_id, env, db_name )
145
+ sub_root = nil
146
+ connect_for( env ) do |con|
147
+ db = con.db( db_name )
148
+ root = Node.new( "home", "home" )
149
+ env_node = Node.new( env, env )
150
+ sub_root = Node.new( parent_id, db_name )
151
+ root << env_node
152
+ env_node << sub_root
153
+
154
+ count = 0
155
+ # excludes = %w[system.indexes]
156
+ data = { :dyna => false }
157
+ db.collection_names.each do |cltn_name|
158
+ # next if excludes.include?( cltn_name )
159
+ size = db[cltn_name].count
160
+ node = Node.new( "#{db_name}_#{count}", "#{cltn_name}(#{size})", data.clone )
161
+ sub_root << node
162
+ count += 1
163
+ end
164
+ end
165
+ sub_root
166
+ end
167
+
168
+ # =========================================================================
169
+ private
170
+
171
+ # Convert size to mb
172
+ def to_mb( val )
173
+ return val if val < 1_000_000
174
+ "#{format_number(val/1_000_000)}Mb"
175
+ end
176
+
177
+ # Add thousand markers
178
+ def format_number( numb )
179
+ numb.to_s.gsub(/(\d)(?=\d{3}+(\.\d*)?$)/, '\1,')
180
+ end
181
+
182
+ # Initialize the mongo installation landscape
183
+ def config
184
+ unless @config
185
+ @config = YAML.load_file( @config_file )
186
+ end
187
+ @config
188
+ end
189
+
190
+ end
191
+ end
@@ -0,0 +1,80 @@
1
+ require 'json'
2
+
3
+ module Mongo3
4
+ class Node
5
+ attr_accessor :oid, :name, :children, :data, :parent
6
+
7
+ def initialize( oid, name, data={} )
8
+ @oid = oid
9
+ @name = name
10
+ @children = []
11
+ @data = data || {}
12
+ @parent = nil
13
+ end
14
+
15
+ # Add a child node
16
+ def <<( new_one )
17
+ new_one.parent = self
18
+ @children << new_one
19
+ update_paths( new_one )
20
+ end
21
+
22
+ def update_paths( node )
23
+ node.data[:crumbs] = node.path( :name )
24
+ node.data[:path] = node.path
25
+ node.children.each do |child|
26
+ child.update_paths( child )
27
+ end
28
+ end
29
+
30
+ # convert a tree node to a set of adjacencies
31
+ def to_adjacencies
32
+ root_level = { :id => self.oid, :name => self.name, :data => self.data, :adjacencies => [] }
33
+ cltn = [ root_level ]
34
+ self.children.each do |child|
35
+ root_level[:adjacencies] << child.oid
36
+ cltn << { :id => child.oid, :name => child.name, :data => child.data, :adjacencies => [] }
37
+ end
38
+ cltn
39
+ end
40
+
41
+ def path( accessor=:oid )
42
+ path = []
43
+ traverse( path, self, accessor )
44
+ path.reverse.join( "|" )
45
+ end
46
+
47
+ def traverse( path, node, accessor )
48
+ path << node.send( accessor ).gsub( /\(\d+\)/, "" )
49
+ if node.parent
50
+ traverse( path, node.parent, accessor )
51
+ end
52
+ end
53
+
54
+ # converts to json
55
+ def to_json(*a)
56
+ {
57
+ 'id' => oid,
58
+ 'name' => self.name,
59
+ 'children' => self.children,
60
+ 'data' => self.data
61
+ }.to_json(*a)
62
+ end
63
+
64
+ # Debug...
65
+
66
+ # Dump nodes to stdout
67
+ def self.dump( node, level=0 )
68
+ puts ' '*level + "%-#{20-level}s (%d) [%s] -- %s" % [node.oid, node.children.size, node.name, (node.data ? node.data.inspect : 'N/A' )]
69
+ node.children.each { |c| dump( c, level+1 ) }
70
+ end
71
+
72
+ # Dump adjancencies to stdout
73
+ def self.dump_adj( adjs, level = 0 )
74
+ adjs.each do |adj|
75
+ puts ' '*level + "%-#{20-level}s (%d) [%s] -- %s" % [adj[:id], adj[:adjacencies].size, adj[:name], (adj[:data] ? adj[:data].inspect : 'N/A' )]
76
+ end
77
+ end
78
+
79
+ end
80
+ end