wackamole 0.0.9 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
  # -----------------------------------------------------------------------