wackamole 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/History.txt +5 -1
  2. data/README.rdoc +12 -3
  3. data/bin/wackamole +2 -2
  4. data/data/fixtures.rb +132 -0
  5. data/features/env.rb +29 -0
  6. data/features/mission.feature +10 -0
  7. data/features/step_definitions/mission_steps.rb +5 -0
  8. data/lib/app.rb +23 -7
  9. data/lib/controllers/features.rb +3 -2
  10. data/lib/controllers/logs.rb +1 -0
  11. data/lib/controllers/mission.rb +14 -4
  12. data/lib/controllers/session.rb +32 -0
  13. data/lib/controllers/users.rb +3 -2
  14. data/lib/helpers/flash_helper.rb +4 -1
  15. data/lib/helpers/logs_helper.rb +2 -1
  16. data/lib/helpers/session_helper.rb +29 -0
  17. data/lib/wackamole.rb +1 -1
  18. data/lib/wackamole/models/control.rb +15 -1
  19. data/lib/wackamole/models/feature.rb +11 -2
  20. data/lib/wackamole/models/log.rb +1 -0
  21. data/lib/wackamole/models/mission.rb +9 -7
  22. data/lib/wackamole/models/mole_info.rb +8 -4
  23. data/lib/wackamole/models/search_filter.rb +48 -15
  24. data/lib/wackamole/models/user.rb +12 -1
  25. data/public/stylesheets/wackamole.css +60 -3
  26. data/spec/config/bogus_test.yml +1 -1
  27. data/spec/config/test.yml +1 -1
  28. data/spec/spec_helper.rb +3 -0
  29. data/spec/ui/log_spec.rb +68 -0
  30. data/spec/ui/mission_spec.rb +64 -0
  31. data/spec/ui/session_spec.rb +39 -0
  32. data/spec/ui_utils/mission_util.rb +41 -0
  33. data/spec/{models → wackamole/models}/control_spec.rb +21 -21
  34. data/spec/{models → wackamole/models}/feature_spec.rb +7 -7
  35. data/spec/{models → wackamole/models}/log_spec.rb +5 -5
  36. data/spec/{models → wackamole/models}/mission_spec.rb +11 -7
  37. data/spec/wackamole/models/moled_info_spec.rb +36 -0
  38. data/spec/{models → wackamole/models}/search_filter_spec.rb +12 -16
  39. data/spec/{models → wackamole/models}/user_spec.rb +5 -5
  40. data/spec/{wackamole_spec.rb → wackamole/wackamole_spec.rb} +2 -2
  41. data/tasks/fixtures.rake +3 -1
  42. data/tasks/setup.rb +2 -1
  43. data/tasks/spec.rake +17 -3
  44. data/views/dashboard/_report.erb +3 -3
  45. data/views/layout.erb +44 -11
  46. data/views/logs/show.erb +3 -0
  47. data/views/mission/_report.erb +2 -2
  48. data/views/session/login.erb +28 -0
  49. data/views/shared/_search.erb +1 -1
  50. data/views/users/index.js.erb +1 -1
  51. metadata +22 -10
  52. data/spec/models/moled_info_spec.rb +0 -30
@@ -27,4 +27,8 @@
27
27
  * Bug fixes and clean up
28
28
 
29
29
  === 0.0.8 /2010-02-21
30
- * Fix bug on mission and local time
30
+ * Fix bug on mission and local time
31
+
32
+ === 0.0.9 /2010-02-28
33
+ * Added console authentication - see README for info
34
+ * Added support for auth on mongo instance - see README for info
@@ -49,12 +49,21 @@
49
49
  a file wackamole.yml. You will need to specify the envs, host and ports specific
50
50
  to your configuration, but here is a sample.
51
51
 
52
- wackamole.yml
52
+ wackamole.yml
53
+
54
+ # New ! Optionally you can specify login name and password for the Wackamole web app.
55
+ console_auth: &auth
56
+ auth:
57
+ user: admin
58
+ password: admin
59
+
53
60
  development:
54
- host: localhost
55
- port: 27017
61
+ <<: *auth
62
+ host: localhost
63
+ port: 27017
56
64
 
57
65
  beta:
66
+ <<: *auth
58
67
  host: beta_host_name
59
68
  port: 27017
60
69
  user: bobo
@@ -7,7 +7,7 @@ URI_MATCH = /(mongo|memcache):\/\/(.+?)\:(\d+)\/(\w+)\/{0,1}(\w*)/
7
7
  Main {
8
8
  option( 'pool=[pool]', 'p' ) {
9
9
  validate { |pool| pool =~ URI_MATCH }
10
- description "specify session server uri. Must be of the form {[mongo|memcache]}://{host}:{port}/{[database_name|namespace]}[/{collection_name}]"
10
+ description "specify session server uri. Must be of the form {[mongo|memcache]}://{host}:{port}/{[database_name|namespace]}[/{collection_name}]. Defaults to local memcached on default port"
11
11
  }
12
12
  option( 'environment', 'e' ) {
13
13
  argument :required
@@ -26,7 +26,7 @@ Main {
26
26
 
27
27
  Thread.new do
28
28
  puts "-"*100
29
- puts "Initializing Wackamole -- Version #{Wackamole::VERSION}"
29
+ puts "Initializing Wackamole -- Version #{Wackamole::VERSION} -- Landscape #{params['environment']}"
30
30
  puts "-"*100
31
31
  puts "\n"*2
32
32
  puts ">>> Waiting for Franky to warm up..."
@@ -0,0 +1,132 @@
1
+ require "rubygems"
2
+ require "mongo"
3
+ require 'rackamole'
4
+ require 'wackamole'
5
+
6
+ class Fixtures
7
+ attr_reader :con
8
+
9
+ def mole_collections() %w(users features logs); end
10
+
11
+ def initialize( host='localhost', port=27099 )
12
+ puts "Loading fixture data"
13
+ @con = Mongo::Connection.new( host, port )
14
+ end
15
+
16
+ def clear
17
+ con.database_names.select do |db_name|
18
+ if db_name =~ /^mole_/
19
+ puts "Dropping db #{db_name}"
20
+ @con.drop_database( db_name )
21
+ end
22
+ end
23
+ end
24
+
25
+ def populate
26
+ clear
27
+ apps = [
28
+ %w(app1 test),
29
+ %w(app2 test)
30
+ ]
31
+ apps.each { |config| create_mole_db( config.first, config.last ) }
32
+ end
33
+
34
+ def create_mole_db( app_name, env )
35
+ db_name = mole_db_name( app_name, env )
36
+ provision( db_name )
37
+ end
38
+
39
+ def provision( db_name )
40
+ db = con.db( db_name )
41
+ clear_collections(db) if db
42
+
43
+ populate_features( db )
44
+ populate_users( db )
45
+ populate_logs( db )
46
+ end
47
+
48
+ def populate_features( db )
49
+ app_name, stage = Wackamole::Control.extract_app_info( db.name )
50
+ %w(/ /normal /params/10 /error /slow /post ).each do |ctx|
51
+ row = {
52
+ :app => app_name,
53
+ :env => stage,
54
+ :did => Time.now.utc.to_date_id.to_s,
55
+ :ctx => ctx
56
+ }
57
+ db['features'].insert( row )
58
+ end
59
+ end
60
+
61
+ def populate_users( db )
62
+ %w(fernand bobo bubba eddie freddie).each do |user|
63
+ row = { :una => user, :did => Time.now.to_date_id }
64
+ db['users'].insert( row )
65
+ end
66
+ end
67
+
68
+ def populate_logs( db )
69
+ logs_cltn = db['logs']
70
+ user_config = {
71
+ 'fernand' => {
72
+ :days => 2,
73
+ :activities => [2, 1, 0]
74
+ },
75
+ 'bobo' => {
76
+ :days => 3,
77
+ :activities => [1, 1, 1]
78
+ }
79
+ }
80
+ user_config.each_pair do |user_name, activity|
81
+ user = db['users'].find_one( { :una => user_name } )
82
+ (0...activity[:days]).each do |day|
83
+ date = Time.now - day*(24*60*60)
84
+ count = 0
85
+ [Rackamole.feature, Rackamole.perf, Rackamole.fault].each do |type|
86
+ create_logs( db, logs_cltn, activity[:activities][count], type, date.utc, user )
87
+ count += 1
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def create_logs( db, logs_cltn, count, type, time, user )
94
+ date_id = time.to_date_id
95
+ features = db['features'].find( {} ).to_a
96
+ (0...count).each do |i|
97
+ time_id = "%02d0100" % (i%23)
98
+ create_log( logs_cltn, type, date_id, time_id, user, features[i%features.size] )
99
+ end
100
+ end
101
+
102
+ def create_log( logs_cltn, type, date_id, time_id, user, feature )
103
+ row = {
104
+ :url => "http://localhost:3000#{feature['ctx']}",
105
+ :typ => type,
106
+ :fid => feature['_id'],
107
+ :hos => 'localhost',
108
+ :met => 'GET',
109
+ :sts => 200,
110
+ :did => date_id.to_s,
111
+ :tid => time_id.to_s,
112
+ :rti => (type == Rackamole.perf ? 10 : 1),
113
+ :bro => { :version => '1.0', :name => 'Firefox' },
114
+ :sof => "thin 1.2.5 codename This Is Not A Web Server",
115
+ :hdr => { 'Content-Type' => 'text/html', 'Content-Length' => 100 },
116
+ :par => { :blee => 10, :duh => "bumblebeetuna" },
117
+ :uid => user['_id'],
118
+ :mac => { :version => 10.6, :platform => 'Macintosh', :os => 'Intel Mac OS X' },
119
+ :ses => { :user_name => user['una'] }
120
+ }
121
+ logs_cltn.insert( row )
122
+ end
123
+
124
+ def mole_db_name( app_name, env )
125
+ "mole_#{app_name}_#{env}_mdb"
126
+ end
127
+
128
+ def clear_collections( db )
129
+ mole_collections.each { |cltn| db.drop_collection( cltn ) }
130
+ end
131
+ end
132
+ # Fixtures.new.populate
@@ -0,0 +1,29 @@
1
+ app_file = File.join( File.dirname(__FILE__), *%w[.. lib app.rb] )
2
+ require app_file
3
+
4
+ # Force the application name because polyglot breaks the auto-detection logic.
5
+ Sinatra::Application.app_file = app_file
6
+
7
+ require 'spec/expectations'
8
+ require 'spec/interop/test'
9
+ require 'rack/test'
10
+ require 'sinatra/test'
11
+ require 'capybara'
12
+
13
+ # Webrat.configure do |config|
14
+ # config.mode = :rack
15
+ # end
16
+
17
+ class MyWorld
18
+ include Rack::Test::Methods
19
+ # include Webrat::Methods
20
+ # include Webrat::Matchers
21
+
22
+ # Webrat::Methods.delegate_to_session :response_code, :response_body
23
+
24
+ def app
25
+ Sinatra::Application
26
+ end
27
+ end
28
+
29
+ World{MyWorld.new}
@@ -0,0 +1,10 @@
1
+ Feature: Manage moled applications
2
+ In order to view my application cruise control
3
+ As a user
4
+ I want to see all my moled applications
5
+
6
+ Scenario: Moles application list
7
+ Given I have applications named App1, App2
8
+ When I go to the mission
9
+ Then I should see App1
10
+ And I should see App2
@@ -0,0 +1,5 @@
1
+ Given /^I have applications named (.+)$/ do |apps|
2
+ apps.split( ', ' ).each do |app|
3
+
4
+ end
5
+ end
data/lib/app.rb CHANGED
@@ -5,6 +5,7 @@ require 'mongo'
5
5
  gem 'agnostic-will_paginate'
6
6
  require 'will_paginate'
7
7
  require 'mongo_rack'
8
+ require 'rack-flash'
8
9
  require 'rackamole'
9
10
  require File.expand_path( File.join( File.dirname(__FILE__), 'wackamole.rb' ) )
10
11
 
@@ -18,9 +19,9 @@ end
18
19
  # -----------------------------------------------------------------------------
19
20
  # Configurations
20
21
 
21
- configure :production do
22
- set :logging, true
23
- end
22
+ # configure :production do
23
+ # set :logging, true
24
+ # end
24
25
 
25
26
  configure do
26
27
  set :sessions, false
@@ -29,6 +30,8 @@ configure do
29
30
  Wackamole.load_all_libs_relative_to(__FILE__, 'helpers' )
30
31
  Wackamole.load_all_libs_relative_to(__FILE__, 'controllers' )
31
32
 
33
+ # use Rack::Flash, :accessorize => [:notice, :error]
34
+
32
35
  #Pick up command line args if any?
33
36
  if defined? @@options and @@options
34
37
  if @@options[:protocol] == 'mongo'
@@ -41,18 +44,31 @@ configure do
41
44
  :namespace => @@options[:namespace]
42
45
  end
43
46
  else
47
+ # Default is local memcache on default port.
48
+ use Rack::Session::Memcache,
49
+ :memcache_server => "%s:%d" % ['localhost', 11211],
50
+ :namespace => 'wackamole'
51
+
44
52
  # Default is a mongo session store
45
- use Rack::Session::Mongo,
46
- :server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions'],
47
- :log_level => :error
53
+ # use Rack::Session::Mongo,
54
+ # :server => "%s:%d/%s/%s" % ['localhost', '27017', 'wackamole_ses', 'sessions'],
55
+ # :log_level => :error
48
56
  end
49
57
  Wackamole::Control.init_config( default_config, Sinatra::Application.environment.to_s )
50
58
  end
51
59
 
52
60
  # -----------------------------------------------------------------------------
53
61
  # Before filters
54
- before do
62
+ before do
55
63
  unless request.path =~ /\.[css gif png js]/
64
+ if console_auth?
65
+ unless request.path == '/' or request.path == '/session/create' or request.path == '/session/delete'
66
+ unless authenticated?
67
+ redirect '/'
68
+ end
69
+ end
70
+ end
71
+
56
72
  @filter = session[:filter]
57
73
  unless @filter
58
74
  @filter = Wackamole::SearchFilter.new
@@ -22,8 +22,9 @@ 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
- logger.error boom
26
- flash[:error] = boom
25
+ puts boom
26
+ flash_it!( :error, boom )
27
+ @filter.search_terms = nil
27
28
  @features = [].paginate
28
29
  end
29
30
 
@@ -22,6 +22,7 @@ module Logs
22
22
  @logs = Wackamole::Log.paginate( @filter.to_conds )
23
23
  rescue => boom
24
24
  # puts boom
25
+ @filter.search_terms = nil
25
26
  flash_it!( :error, boom )
26
27
  @logs = [].paginate
27
28
  end
@@ -2,15 +2,25 @@ require 'chronic'
2
2
 
3
3
  module Mission
4
4
  # ---------------------------------------------------------------------------
5
- get '/' do
6
- # reset app info
5
+ get '/mission' do
6
+ clear_flash!
7
+
8
+ # reset app info
7
9
  session[:app_info] = @app_info = nil
8
10
 
11
+ # Support store like mongodb where not allowed to peruse connection
12
+ # in which case just show the dashboard
13
+ if Wackamole::Control.single_app?
14
+ app_name, stage = Wackamole::Control.app_info
15
+ redirect "/dashboard/#{app_name}/#{stage}"
16
+ return
17
+ end
18
+
9
19
  last_tick = session[:last_tick]
10
20
  last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
11
21
  session[:last_tick] = Time.now
12
22
 
13
- @pulse = Wackamole::Mission.pulse( last_tick.utc )
23
+ @pulse = Wackamole::Mission.pulse( last_tick )
14
24
 
15
25
  erb :'mission/index'
16
26
  end
@@ -21,7 +31,7 @@ module Mission
21
31
  last_tick ||= Chronic.parse( "#{@refresh_rate} seconds ago" )
22
32
  session[:last_tick] = Time.now
23
33
 
24
- @pulse = Wackamole::Mission.pulse( last_tick.utc )
34
+ @pulse = Wackamole::Mission.pulse( last_tick )
25
35
 
26
36
  erb :'/mission/refresh_js', :layout => false
27
37
  end
@@ -0,0 +1,32 @@
1
+ module Session
2
+
3
+ # ---------------------------------------------------------------------------
4
+ # Check auth
5
+ get "/" do
6
+ if console_auth?
7
+ # clear_flash!
8
+ erb :'session/login'
9
+ else
10
+ redirect '/mission'
11
+ end
12
+ end
13
+
14
+ # ---------------------------------------------------------------------------
15
+ # Log out
16
+ get "/session/delete" do
17
+ session.clear
18
+ redirect '/'
19
+ end
20
+
21
+ # ---------------------------------------------------------------------------
22
+ # Check credentials
23
+ post "/session/create" do
24
+ if authenticate( params[:login] )
25
+ session[:user] = params[:login][:username]
26
+ redirect '/mission'
27
+ else
28
+ flash_it!( :error, "Authentication failed! Please check credentials." )
29
+ redirect '/'
30
+ end
31
+ end
32
+ end
@@ -23,8 +23,9 @@ module Users
23
23
  @filter.search_terms = params[:search_filter][:search_terms]
24
24
  @users = Wackamole::User.paginate_tops( @filter.to_conds )
25
25
  rescue => boom
26
- logger.error boom
27
- flash[:error] = boom
26
+ puts boom
27
+ @filter.search_terms = nil
28
+ flash_it!( :error, boom )
28
29
  @users = [].paginate
29
30
  end
30
31
 
@@ -2,15 +2,18 @@ module FlashHelper
2
2
  helpers do
3
3
 
4
4
  # clear out flash object
5
- def clear_it!
5
+ def clear_flash!
6
6
  @flash = session[:flash] || OrderedHash.new
7
7
  @flash.clear
8
+ session[:flash] = @flash
8
9
  end
9
10
 
10
11
  # add flash message
11
12
  def flash_it!( type, msg )
12
13
  @flash = session[:flash] || OrderedHash.new
13
14
  @flash[type] = msg
15
+ session[:flash] = @flash
16
+ puts @flash.inspect
14
17
  end
15
18
  end
16
19
  end
@@ -79,7 +79,8 @@ module LogsHelper
79
79
 
80
80
  # ---------------------------------------------------------------------------
81
81
  # Trim out extra host info if any
82
- def format_host( host )
82
+ def format_host( host )
83
+ return "n/a" unless host or host.empty?
83
84
  return host.split( "." ).first if host.index( /\./ )
84
85
  host
85
86
  end
@@ -0,0 +1,29 @@
1
+ module SessionHelper
2
+ helpers do
3
+
4
+ # Check credentials against config file
5
+ def authenticate( creds )
6
+ env = Sinatra::Application.environment.to_s
7
+ config = YAML.load_file( default_config )
8
+ conf = config[env]
9
+ ((creds['username'] == conf['auth']['user']) and (creds['password'] == conf['auth']['password']))
10
+ end
11
+
12
+ def console_auth?
13
+ env = Sinatra::Application.environment.to_s
14
+ config = YAML.load_file( default_config )
15
+ conf = config[env]
16
+ conf['auth']
17
+ end
18
+
19
+ # Check if session has auth
20
+ def authenticated?
21
+ session[:user]
22
+ end
23
+
24
+ # check for login path
25
+ def root_path?
26
+ request.path == "/"
27
+ end
28
+ end
29
+ end