wackamole 0.0.9 → 0.1.2

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.
Files changed (40) hide show
  1. data/History.txt +4 -1
  2. data/README.rdoc +17 -17
  3. data/Rakefile +1 -1
  4. data/bin/wackamole +5 -3
  5. data/lib/app.rb +13 -13
  6. data/lib/controllers/dashboard.rb +7 -2
  7. data/lib/controllers/features.rb +1 -1
  8. data/lib/controllers/logs.rb +20 -1
  9. data/lib/controllers/mission.rb +7 -8
  10. data/lib/controllers/session.rb +0 -1
  11. data/lib/controllers/users.rb +5 -1
  12. data/lib/helpers/dashboard_helper.rb +7 -2
  13. data/lib/helpers/flash_helper.rb +0 -1
  14. data/lib/helpers/main_helper.rb +6 -0
  15. data/lib/helpers/session_helper.rb +9 -6
  16. data/lib/wackamole.rb +1 -1
  17. data/lib/wackamole/models/control.rb +58 -31
  18. data/lib/wackamole/models/feature.rb +1 -1
  19. data/lib/wackamole/models/log.rb +1 -2
  20. data/lib/wackamole/models/mission.rb +49 -46
  21. data/lib/wackamole/models/mole_info.rb +4 -5
  22. data/lib/wackamole/models/search_filter.rb +2 -2
  23. data/lib/wackamole/models/user.rb +1 -1
  24. data/public/stylesheets/wackamole.css +41 -14
  25. data/spec/config/test.yml +4 -3
  26. data/spec/data/fixtures.rb +92 -92
  27. data/spec/spec_helper.rb +2 -1
  28. data/spec/wackamole/models/control_spec.rb +27 -33
  29. data/spec/wackamole/models/feature_spec.rb +19 -20
  30. data/spec/wackamole/models/log_spec.rb +2 -3
  31. data/spec/wackamole/models/mission_spec.rb +16 -18
  32. data/spec/wackamole/models/moled_info_spec.rb +9 -10
  33. data/spec/wackamole/models/search_filter_spec.rb +4 -5
  34. data/spec/wackamole/models/user_spec.rb +2 -3
  35. data/views/features/_rows.erb +1 -1
  36. data/views/layout.erb +18 -26
  37. data/views/logs/show.erb +6 -4
  38. data/views/mission/_report.erb +39 -39
  39. data/views/users/_rows.erb +2 -2
  40. metadata +11 -11
@@ -31,4 +31,7 @@
31
31
 
32
32
  === 0.0.9 /2010-02-28
33
33
  * Added console authentication - see README for info
34
- * Added support for auth on mongo instance - see README for info
34
+ * Added support for auth on mongo instance - see README for info
35
+
36
+ === 0.1.0 /2010-03-10
37
+ * Cleaning up
@@ -44,12 +44,14 @@
44
44
 
45
45
  === Configure It!
46
46
 
47
+ !!! WARNING File format change from 0.1.2 on !!!
48
+
47
49
  You will need to give wackamole some information about your rackamole configuration.
48
- In order to do so create a .wackamole directory in your home directory and create
49
- a file wackamole.yml. You will need to specify the envs, host and ports specific
50
+ In order to do so, create a .wackamole directory in your home directory and create
51
+ a file zones.yml. You will need to specify the envs, host and ports specific
50
52
  to your configuration, but here is a sample.
51
53
 
52
- wackamole.yml
54
+ zones.yml
53
55
 
54
56
  # New ! Optionally you can specify login name and password for the Wackamole web app.
55
57
  console_auth: &auth
@@ -57,24 +59,22 @@
57
59
  user: admin
58
60
  password: admin
59
61
 
60
- development:
61
- <<: *auth
62
- host: localhost
63
- port: 27017
64
-
65
- beta:
66
- <<: *auth
67
- host: beta_host_name
68
- port: 27017
69
- user: bobo
70
- password: secret
62
+ zones:
63
+ local:
64
+ host: localhost
65
+ port: 27017
66
+
67
+ staging:
68
+ host: beta_host_name
69
+ port: 27017
70
+ user: bobo
71
+ password: secret
71
72
 
72
73
  === Launch It!
73
74
 
74
75
  Watch your creation live!
75
76
 
76
- NOTE: By default wackamole uses mongo_rack for storing its session information.
77
- This assumes that you have a local mongoDB instance running on the default port 27017.
77
+ NOTE: By default wackamole uses memcache for storing its session information.
78
78
 
79
79
  > wackamole
80
80
 
@@ -95,7 +95,7 @@
95
95
 
96
96
  To launch wackamole in a given environment defined in your wackamole.yml configuration.
97
97
 
98
- > wackamole -e env
98
+ > wackamole -e env
99
99
 
100
100
  This option defaults to production.
101
101
 
data/Rakefile CHANGED
@@ -29,11 +29,11 @@ PROJ.spec.opts << '--color'
29
29
  PROJ.rdoc.include = %w[.rb]
30
30
 
31
31
  # Dependencies
32
+ depend_on "rack" , ">= 1.1.0"
32
33
  depend_on "mongo" , ">= 0.18.1"
33
34
  depend_on "mongo_ext" , ">= 0.18.1"
34
35
  depend_on "agnostic-will_paginate", ">= 3.0.0"
35
36
  depend_on "memcache-client" , ">= 1.5.0"
36
- depend_on "mongo_rack" , ">= 0.0.1"
37
37
  depend_on "main" , ">= 4.2.0"
38
38
  depend_on "sinatra" , ">= 0.9.4"
39
39
  depend_on "mongo_rack" , ">= 0.0.3"
@@ -19,14 +19,16 @@ Main {
19
19
 
20
20
  # Enter main loop
21
21
  def run
22
+ puts params[:pool].inspect
23
+ puts params[:environment].inspect
22
24
  require File.expand_path( File.join(File.dirname(__FILE__), %w[.. lib wackamole]))
23
25
 
24
26
  @@options = parse_args( params[:pool].value )
25
- ENV['RACK_ENV'] = params['environment'].value
27
+ ENV['RACK_ENV'] = params[:environment].value
26
28
 
27
29
  Thread.new do
28
30
  puts "-"*100
29
- puts "Initializing Wackamole -- Version #{Wackamole::VERSION} -- Landscape #{params['environment']}"
31
+ puts "Initializing Wackamole -- Version #{Wackamole::VERSION} -- Landscape #{params[:environment].value}"
30
32
  puts "-"*100
31
33
  puts "\n"*2
32
34
  puts ">>> Waiting for Franky to warm up..."
@@ -81,4 +83,4 @@ Main {
81
83
  end
82
84
  opts
83
85
  end
84
- }
86
+ }
data/lib/app.rb CHANGED
@@ -5,7 +5,6 @@ require 'mongo'
5
5
  gem 'agnostic-will_paginate'
6
6
  require 'will_paginate'
7
7
  require 'mongo_rack'
8
- require 'rack-flash'
9
8
  require 'rackamole'
10
9
  require File.expand_path( File.join( File.dirname(__FILE__), 'wackamole.rb' ) )
11
10
 
@@ -13,14 +12,15 @@ set :public, File.join( File.dirname(__FILE__), %w[.. public] )
13
12
  set :views , File.join( File.dirname(__FILE__), %w[.. views] )
14
13
 
15
14
  def default_config
16
- File.join( ENV['HOME'], %w[.wackamole wackamole.yml] )
15
+ File.join( ENV['HOME'], %w[.wackamole zones.yml] )
17
16
  end
18
17
 
19
18
  # -----------------------------------------------------------------------------
20
19
  # Configurations
21
20
 
22
21
  # configure :production do
23
- # set :logging, true
22
+ # set :logging, true
23
+ # set :sessions, true
24
24
  # end
25
25
 
26
26
  configure do
@@ -29,8 +29,6 @@ configure do
29
29
 
30
30
  Wackamole.load_all_libs_relative_to(__FILE__, 'helpers' )
31
31
  Wackamole.load_all_libs_relative_to(__FILE__, 'controllers' )
32
-
33
- # use Rack::Flash, :accessorize => [:notice, :error]
34
32
 
35
33
  #Pick up command line args if any?
36
34
  if defined? @@options and @@options
@@ -54,7 +52,7 @@ configure do
54
52
  # :server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions'],
55
53
  # :log_level => :error
56
54
  end
57
- Wackamole::Control.init_config( default_config, Sinatra::Application.environment.to_s )
55
+ Wackamole::Control.init_config( default_config )
58
56
  end
59
57
 
60
58
  # -----------------------------------------------------------------------------
@@ -77,12 +75,14 @@ before do
77
75
  @updated_on = Time.now
78
76
  @refresh_rate = 30
79
77
  @app_info = session[:app_info]
80
- begin
81
- Wackamole::Control.switch_mole_db!( @app_info[:app_name].downcase, @app_info[:stage] ) if @app_info
82
- rescue => boom
83
- $stderr.puts boom
84
- @app_info = nil
85
- session[:app_info] = nil
86
- end
78
+ Wackamole::Control.ensure_db( session[:context] ) if session[:context]
79
+
80
+ # begin
81
+ # Wackamole::Control.switch_mole_db!( @app_info[:app].downcase, @app_info[:stage] ) if @app_info
82
+ # rescue => boom
83
+ # $stderr.puts boom
84
+ # @app_info = nil
85
+ # session[:app_info] = nil
86
+ # end
87
87
  end
88
88
  end
@@ -5,8 +5,12 @@ module Dashboard
5
5
 
6
6
  # ---------------------------------------------------------------------------
7
7
  # Show application dashboard
8
- get '/dashboard/:app_name/:stage' do
9
- Wackamole::Control.switch_mole_db!( params[:app_name].downcase, params[:stage] )
8
+ get '/dashboard/:zone/:app/:stage' do
9
+ zone = params[:zone]
10
+ app = params[:app]
11
+ stage = params[:stage]
12
+
13
+ switch_context!( zone, app, stage )
10
14
 
11
15
  @info = Wackamole::MoledInfo.collect_dashboard_info( @updated_on )
12
16
 
@@ -22,6 +26,7 @@ module Dashboard
22
26
  # ---------------------------------------------------------------------------
23
27
  # Refresh dashboard
24
28
  get '/dashboard/refresh' do
29
+ Wackamole::Control.ensure_db( session[:context] )
25
30
  @info = Wackamole::MoledInfo.collect_dashboard_info( @updated_on )
26
31
 
27
32
  erb :'dashboard/refresh_js', :layout => false
@@ -22,7 +22,7 @@ module Features
22
22
  @filter.search_terms = params[:search_filter][:search_terms]
23
23
  @features = Wackamole::Feature.paginate_tops( @filter.to_conds )
24
24
  rescue => boom
25
- puts boom
25
+ # puts boom
26
26
  flash_it!( :error, boom )
27
27
  @filter.search_terms = nil
28
28
  @features = [].paginate
@@ -39,7 +39,7 @@ module Logs
39
39
 
40
40
  # ---------------------------------------------------------------------------
41
41
  # Filter logs
42
- post "/logs/filter" do
42
+ post "/logs/filter" do
43
43
  @filter = Wackamole::SearchFilter.new
44
44
  @filter.from_options( params[:filter] )
45
45
  session[:filter] = @filter
@@ -47,4 +47,23 @@ module Logs
47
47
  @logs = Wackamole::Log.paginate( @filter.to_conds )
48
48
  erb :"logs/filter.js", :layout => false
49
49
  end
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # Show logs for a given user
53
+ get "/logs/user/:username" do
54
+ @filter.search_terms = "user:#{params[:username]}"
55
+ session[:filter] = @filter
56
+
57
+ redirect '/logs/1'
58
+ end
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # Show logs for a given feature
62
+ get "/logs/feature/:feature_id" do
63
+ @filter.feature_id = params[:feature_id]
64
+ session[:filter] = @filter
65
+
66
+ redirect '/logs/1'
67
+ end
68
+
50
69
  end
@@ -20,8 +20,8 @@ module Mission
20
20
  last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
21
21
  session[:last_tick] = Time.now
22
22
 
23
- @pulse = Wackamole::Mission.pulse( last_tick )
24
-
23
+ @zones = Wackamole::Mission.pulse( last_tick )
24
+
25
25
  erb :'mission/index'
26
26
  end
27
27
 
@@ -31,19 +31,18 @@ module Mission
31
31
  last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
32
32
  session[:last_tick] = Time.now
33
33
 
34
- @pulse = Wackamole::Mission.pulse( last_tick )
34
+ @zones = Wackamole::Mission.pulse( last_tick )
35
35
 
36
36
  erb :'/mission/refresh_js', :layout => false
37
37
  end
38
38
 
39
39
  # ---------------------------------------------------------------------------
40
- get '/mission/logs/:app_name/:stage/:type' do
41
- Wackamole::Control.switch_mole_db!( params[:app_name].downcase, params[:stage] )
40
+ get '/mission/logs/:zone/:app/:stage/:type' do
41
+ switch_context!( params[:zone], params[:app], params[:stage] )
42
42
 
43
43
  # Set app info
44
- @app_info = Wackamole::Feature.get_app_info
45
- session[:app_info] = @app_info
46
-
44
+ load_app_info
45
+
47
46
  # Reset filter
48
47
  filter = Wackamole::SearchFilter.new
49
48
  filter.mole_type( params[:type].to_i )
@@ -4,7 +4,6 @@ module Session
4
4
  # Check auth
5
5
  get "/" do
6
6
  if console_auth?
7
- # clear_flash!
8
7
  erb :'session/login'
9
8
  else
10
9
  redirect '/mission'
@@ -4,6 +4,9 @@ module Users
4
4
  # Paginate top users
5
5
  get "/users/:page" do
6
6
  page = params[:page] ? params[:page].to_i : 1
7
+
8
+ Wackamole::Control.ensure_db( session[:context] )
9
+
7
10
  @users = Wackamole::User.paginate_tops( @filter.to_conds, page )
8
11
 
9
12
  @search_path = "/users/search"
@@ -23,7 +26,7 @@ module Users
23
26
  @filter.search_terms = params[:search_filter][:search_terms]
24
27
  @users = Wackamole::User.paginate_tops( @filter.to_conds )
25
28
  rescue => boom
26
- puts boom
29
+ # puts boom
27
30
  @filter.search_terms = nil
28
31
  flash_it!( :error, boom )
29
32
  @users = [].paginate
@@ -40,4 +43,5 @@ module Users
40
43
  @users = Wackamole::User.paginate_tops( @filter.to_conds )
41
44
  erb :"users/filter.js", :layout => false
42
45
  end
46
+
43
47
  end
@@ -13,9 +13,14 @@ module DashboardHelper
13
13
  # -------------------------------------------------------------------------
14
14
  # Retrieve moled app info...
15
15
  def load_app_info
16
- @app_info = Wackamole::Feature.get_app_info
16
+ tokens = session[:context].split( "." )
17
+
18
+ @app_info = {}
19
+ @app_info[:zone] = tokens[0]
20
+ @app_info[:app] = tokens[1]
21
+ @app_info[:stage] = tokens[2]
17
22
  session[:app_info] = @app_info
18
- end
23
+ end
19
24
 
20
25
  # -------------------------------------------------------------------------
21
26
  # Loads the application details
@@ -13,7 +13,6 @@ module FlashHelper
13
13
  @flash = session[:flash] || OrderedHash.new
14
14
  @flash[type] = msg
15
15
  session[:flash] = @flash
16
- puts @flash.inspect
17
16
  end
18
17
  end
19
18
  end
@@ -15,6 +15,12 @@ module MainHelper
15
15
  helpers do
16
16
  include WillPaginate::ViewHelpers::Base
17
17
 
18
+ # Change mole context and reset connection if need be
19
+ def switch_context!( zone, app, stage )
20
+ session[:context] = "#{zone}.#{app}.#{stage}"
21
+ Wackamole::Control.current_db( zone, app, stage, true )
22
+ end
23
+
18
24
  def pluralize( count, name )
19
25
  count.to_s + " " + name + (count.to_i > 1 ? "s" : "")
20
26
  end
@@ -3,17 +3,20 @@ module SessionHelper
3
3
 
4
4
  # Check credentials against config file
5
5
  def authenticate( creds )
6
- env = Sinatra::Application.environment.to_s
7
6
  config = YAML.load_file( default_config )
8
- conf = config[env]
9
- ((creds['username'] == conf['auth']['user']) and (creds['password'] == conf['auth']['password']))
7
+ auth = config['console_auth']
8
+
9
+ # No auth. Let it go
10
+ return true unless auth
11
+
12
+ # Validate creds
13
+ ((creds['username'] == auth['user']) and (creds['password'] == auth['password']))
10
14
  end
11
15
 
16
+ # Check if auth is defined
12
17
  def console_auth?
13
- env = Sinatra::Application.environment.to_s
14
18
  config = YAML.load_file( default_config )
15
- conf = config[env]
16
- conf['auth']
19
+ config['console_auth']
17
20
  end
18
21
 
19
22
  # Check if session has auth
@@ -1,7 +1,7 @@
1
1
  module Wackamole
2
2
 
3
3
  # :stopdoc:
4
- VERSION = '0.0.9' unless defined? Wackamole::VERSION
4
+ VERSION = '0.1.2' unless defined? Wackamole::VERSION
5
5
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR unless defined? Wackamole::LIBPATH
6
6
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR unless defined? Wackamole::PATH
7
7
  # :startdoc:
@@ -1,34 +1,38 @@
1
1
  require 'mongo'
2
2
  require 'logger'
3
3
 
4
+ # BOZO !! Refact and clean up duds
4
5
  module Wackamole
5
6
  class Control
6
7
 
7
8
  # -----------------------------------------------------------------------
8
9
  # Initialize app by reading off mongo configuration parameters if necessary
9
- def self.init_config( config_file, env )
10
+ def self.init_config( config_file )
10
11
  begin
11
- config = YAML.load_file( config_file )
12
- @config = config[env]
13
- raise "Invalid environment `#{env}" unless @config
14
- raise "Unable to find host in - #{@config.inspect}" unless @config.has_key?('host')
15
- raise "Unable to find port in - #{@config.inspect}" unless @config.has_key?('port')
12
+ @config = YAML.load_file( config_file )
13
+ raise "Unable to find zones definition" unless @config['zones']
16
14
  rescue => boom
17
15
  @config = nil
18
16
  raise "Hoy! An error occur loading the config file `#{config_file} -- #{boom}"
19
17
  end
20
18
  @config
21
19
  end
20
+
21
+ # -------------------------------------------------------------------------
22
+ # List all available zones
23
+ def self.zones
24
+ @config['zones'].keys
25
+ end
22
26
 
23
27
  # -------------------------------------------------------------------------
24
28
  # Defines mole db identity
25
- def self.molex() @molex || /mole_(.*)?_(.*)?_mdb/; end
29
+ def self.molex() @molex ||= /mole_(.*)?_(.*)?_mdb/; end
26
30
 
27
31
  # -------------------------------------------------------------------------
28
32
  # Fetch a collection on a given database by name
29
33
  def self.collection( cltn_name, db_name=nil, opts={:strict => true} )
30
- # reset_db!( db_name ) if db_name
31
- db( db_name, opts ).collection( cltn_name )
34
+ raise "Unable to locate current database" unless @db
35
+ @db.collection( cltn_name )
32
36
  end
33
37
 
34
38
  # -------------------------------------------------------------------------
@@ -39,23 +43,40 @@ module Wackamole
39
43
  end
40
44
 
41
45
  # -------------------------------------------------------------------------
42
- # Switch db instance given db_name
43
- # NOTE : This assumes mole db naming convention
44
- # ie mole_{app_name in lower case}_{env}_mdb
45
- def self.switch_mole_db!( app_name, env )
46
- raise "You must specify an app name and environment" unless app_name and env
47
- app = app_name.gsub( /\s/, '_' ).downcase
46
+ # Makes sure we're in the right context
47
+ def self.ensure_db( context )
48
+ tokens = context.split( "." )
49
+ current_db( *tokens )
50
+ end
51
+
52
+ # -------------------------------------------------------------------------
53
+ # Set current database
54
+ def self.current_db( zone, app_name, env, reset=false )
55
+ return @db if @db and !reset
56
+ app = app_name.gsub( /\s/, '_' ).downcase
48
57
  db_name = to_mole_db( app_name, env )
49
- raise "Invalid mole database #{db_name}" unless mole_db?( db_name )
50
- reset_db!( db_name )
51
- @db
58
+
59
+ @db = connection( zone ).db( db_name )
52
60
  end
53
61
 
62
+ # # -------------------------------------------------------------------------
63
+ # # Switch db instance given db_name
64
+ # # NOTE : This assumes mole db naming convention
65
+ # # ie mole_{app_name in lower case}_{env}_mdb
66
+ # def self.switch_mole_db!( zone, app_name, env )
67
+ # raise "You must specify an app name and environment" unless app_name and env
68
+ # app = app_name.gsub( /\s/, '_' ).downcase
69
+ # db_name = to_mole_db( app_name, env )
70
+ # raise "Invalid mole database #{db_name}" unless mole_db?( zone, db_name )
71
+ # reset_db!( zone, db_name )
72
+ # @db
73
+ # end
74
+
54
75
  # -------------------------------------------------------------------------
55
76
  # Inspect current connection databases and weed out mole_xxx databases
56
- def self.mole_databases
57
- connection.database_names.select do |db_name|
58
- db_name if mole_db?( db_name )
77
+ def self.mole_databases( zone )
78
+ connection( zone ).database_names.select do |db_name|
79
+ db_name if mole_db?( zone, db_name )
59
80
  end
60
81
  end
61
82
 
@@ -78,17 +99,17 @@ module Wackamole
78
99
 
79
100
  # -----------------------------------------------------------------------
80
101
  # Checks if this is a mole database
81
- def self.mole_db?( db_name )
102
+ def self.mole_db?( zone, db_name )
82
103
  return false unless db_name =~ molex
83
- db = connection.db( db_name )
84
- db.authenticate( config['username'], config['password'] )
104
+ db = connection( zone ).db( db_name )
105
+ db.authenticate( config['username'], config['password'] ) if config['usernane'] and config['password']
85
106
  cltns = db.collection_names
86
107
  return ((%w[users features logs] & cltns).size == 3)
87
108
  end
88
109
 
89
110
  # -----------------------------------------------------------------------
90
111
  # Ensures we have the right db connection
91
- def self.reset_db!( db_name )
112
+ def self.reset_db!( zone, db_name )
92
113
  return if @db and @db.name == db_name
93
114
  @db = nil
94
115
  db( db_name )
@@ -114,22 +135,28 @@ module Wackamole
114
135
 
115
136
  # -----------------------------------------------------------------------
116
137
  # Connects to mongo instance if necessary...
117
- def self.connection( log=false )
138
+ def self.connection( zone, log=false )
139
+ @connections ||= {}
140
+
141
+ return @connections[zone] if @connections[zone]
142
+
118
143
  logger = nil
119
144
  if log
120
145
  logger = Logger.new($stdout)
121
146
  logger.level = Logger::DEBUG
122
147
  end
123
- @connection ||= Mongo::Connection.new( config['host'], config['port'], :logger => logger )
148
+
149
+ host = config['zones'][zone]['host']
150
+ port = config['zones'][zone]['port']
151
+ @connections[zone] = Mongo::Connection.new( host, port, :logger => logger )
152
+ @connections[zone]
124
153
  end
125
154
 
126
155
  # -----------------------------------------------------------------------
127
156
  # Fetch database instance
128
- def self.db( db_name=nil, opts={:strict => true} )
129
- return @db if @db and !db_name
130
- return @db if @db and @db.name == db_name
157
+ def self.db( zone, db_name=nil, opts={:strict => true} )
131
158
  raise "No database specified" unless db_name
132
- @db = connection.db( db_name, opts )
159
+ connection( zone ).db( db_name, opts )
133
160
  end
134
161
 
135
162
  # -----------------------------------------------------------------------