Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'next'

  • Loading branch information...
commit 71125c2924c47f618d485afc4fb2c6d860a59d07 2 parents 4c484f2 + e5e68e1
@nicklewis nicklewis authored
Showing with 510 additions and 335 deletions.
  1. +8 −0 app/controllers/application_controller.rb
  2. +1 −0  app/controllers/node_classes_controller.rb
  3. +1 −0  app/controllers/node_groups_controller.rb
  4. +28 −7 app/controllers/nodes_controller.rb
  5. +5 −6 app/controllers/pages_controller.rb
  6. +32 −9 app/helpers/application_helper.rb
  7. +7 −2 app/helpers/paginate_scope_helper.rb
  8. +5 −16 app/models/node.rb
  9. +4 −0 app/models/node_class.rb
  10. +4 −0 app/models/node_group.rb
  11. +1 −1  app/models/timeline_event.rb
  12. +7 −7 app/views/node_classes/index.html.haml
  13. +7 −7 app/views/node_groups/index.html.haml
  14. +0 −27 app/views/nodes/_actions.html.haml
  15. 0  app/views/nodes/_hidden.html.haml
  16. +0 −16 app/views/nodes/_node.html.haml
  17. +5 −1 app/views/nodes/_nodes.html.haml
  18. +9 −3 app/views/nodes/show.html.haml
  19. +2 −2 app/views/pages/home.html.haml
  20. +1 −1  app/views/shared/_classes.html.haml
  21. +5 −1 app/views/shared/_global_nav.html.haml
  22. +10 −5 app/views/shared/_node_manager_sidebar.html.haml
  23. +1 −1  config/environment.rb
  24. +4 −3 config/routes.rb
  25. +3 −0  config/settings.yml.example
  26. +9 −0 db/migrate/20101118222325_add_hidden_to_nodes.rb
  27. +2 −1  db/schema.rb
  28. +1 −1  ext/packaging/debian/changelog
  29. +6 −1 lib/settings_reader.rb
  30. +23 −0 lib/tasks/package.rake
  31. +0 −1  public/stylesheets/application.css
  32. +0 −1  public/stylesheets/sass/application.scss
  33. +213 −131 spec/controllers/nodes_controller_spec.rb
  34. +26 −0 spec/controllers/pages_controller_spec.rb
  35. +31 −1 spec/helpers/application_helper_spec.rb
  36. +10 −0 spec/helpers/paginate_scope_helper_spec.rb
  37. +28 −54 spec/models/node_spec.rb
  38. +5 −1 spec/shared_behaviors/controller_mixins.rb
  39. +6 −0 spec/spec_helper.rb
  40. +0 −12 spec/views/nodes/_actions.html.haml_spec.rb
  41. +0 −16 spec/views/nodes/_node.html.haml_spec.rb
View
8 app/controllers/application_controller.rb
@@ -17,6 +17,14 @@ class ApplicationController < ActionController::Base
private
+ def raise_unless_using_external_node_classification
+ raise NodeClassificationDisabledError.new unless SETTINGS.use_external_node_classification
+ end
+
+ rescue_from NodeClassificationDisabledError do |e|
+ render :text => "Node classification has been disabled", :content_type => 'text/plain', :status => 403
+ end
+
def set_timezone
if SETTINGS.time_zone
time_zone_obj = ActiveSupport::TimeZone.new(SETTINGS.time_zone)
View
1  app/controllers/node_classes_controller.rb
@@ -1,5 +1,6 @@
class NodeClassesController < InheritedResources::Base
respond_to :html, :json
+ before_filter :raise_unless_using_external_node_classification
include SearchableIndex
end
View
1  app/controllers/node_groups_controller.rb
@@ -1,5 +1,6 @@
class NodeGroupsController < InheritedResources::Base
respond_to :html, :json
+ before_filter :raise_unless_using_external_node_classification
include SearchableIndex
end
View
35 app/controllers/nodes_controller.rb
@@ -2,14 +2,13 @@ class NodesController < InheritedResources::Base
belongs_to :node_class, :optional => true
belongs_to :node_group, :optional => true
respond_to :html, :yaml, :json
+ before_filter :raise_unless_using_external_node_classification, :only => [:new, :edit, :create, :update, :destroy]
layout lambda {|c| c.request.xhr? ? false : 'application' }
def index
raise NodeClassificationDisabledError.new if !SETTINGS.use_external_node_classification and request.format == :yaml
- scoped_index
- rescue NodeClassificationDisabledError => e
- render :text => "Node classification has been disabled", :content_type => 'text/plain', :status => 403
+ scoped_index :unhidden
end
def successful
@@ -21,11 +20,15 @@ def failed
end
def unreported
- scoped_index :unreported
+ scoped_index :unhidden, :unreported
end
def no_longer_reporting
- scoped_index :no_longer_reporting
+ scoped_index :unhidden, :no_longer_reporting
+ end
+
+ def hidden
+ scoped_index :hidden
end
def search
@@ -56,6 +59,24 @@ def show
end
end
+ def hide
+ respond_to do |format|
+ resource.hidden = true
+ resource.save!
+
+ format.html { redirect_to node_path(resource) }
+ end
+ end
+
+ def unhide
+ respond_to do |format|
+ resource.hidden = false
+ resource.save!
+
+ format.html { redirect_to node_path(resource) }
+ end
+ end
+
def facts
respond_to do |format|
format.html {
@@ -93,13 +114,13 @@ def resource
end
# Render the index using the +scope_name+ (e.g. :successful for Node.successful).
- def scoped_index(scope_name=nil)
+ def scoped_index(*scope_names)
index! do |format|
scope = end_of_association_chain
if params[:q]
scope = scope.search(params[:q])
end
- if scope_name
+ scope_names.each do |scope_name|
scope = scope.send(scope_name)
end
if params[:current].present? or params[:successful].present?
View
11 app/controllers/pages_controller.rb
@@ -1,12 +1,11 @@
class PagesController < ApplicationController
def home
- @statuses = Status.by_interval(:limit => 30)
+ @currently_failing_nodes = Node.by_currentness_and_successfulness(true, false).unhidden
+ @unreported_nodes = Node.unreported.unhidden
+ @no_longer_reporting_nodes = Node.no_longer_reporting.unhidden
+ @recently_reported_nodes = Node.reported.by_report_date.unhidden.all(:limit => 10)
- @currently_failing_nodes = Node.by_currentness_and_successfulness(true, false)
- @unreported_nodes = Node.unreported
- @no_longer_reporting_nodes = Node.no_longer_reporting
-
- @nodes = Node.by_report_date.all(:limit => 10)
+ @unhidden_nodes = Node.unhidden
end
def release_notes
View
41 app/helpers/application_helper.rb
@@ -44,11 +44,11 @@ def inspector_table(collection, key=nil, value=nil, options={})
collection_hash_values = collection.map{ |c|
[
- key.respond_to?(:call) ?
- key.call(c) :
+ key.respond_to?(:call) ?
+ key.call(c) :
link_to_if(options[:link], c.send(key), c),
- value ?
- (value.respond_to?(:call) ? value.call(c) : c.send(value)) :
+ value ?
+ (value.respond_to?(:call) ? value.call(c) : c.send(value)) :
false
]
}
@@ -94,19 +94,42 @@ def focus(target)
def header_for(form)
content_tag(:h2, :class => "header") do
(form.object.new_record? ? "Add" : "Edit") + " " + form.object.class.name.titleize.downcase
- end
+ end
end
include WillPaginate::ViewHelpers
# Return HTML with pagination controls for displaying an ActiveRecord +scope+.
def pagination_for(scope, more_link=nil)
- if scope.respond_to?(:total_pages) && scope.total_pages > 1
- content_tag(:div, :class => 'actionbar') do
+ content_tag(:div, :class => 'actionbar') do
+ if scope.respond_to?(:total_pages) && scope.total_pages > 1
[
- more_link ? content_tag(:span, :class => 'pagination') { link_to('More &raquo;', more_link) } : will_paginate(scope),
- tag(:br, :class=> 'clear')
+ more_link ? content_tag(:span, :class => 'pagination') { link_to('More &raquo;', more_link) } : will_paginate(scope),
+ content_tag(:div, :class => 'pagination') do
+ ' | '
+ end
]
+ else
+ []
+ end +
+ [
+ pagination_sizer_for(scope),
+ tag(:br, :class=> 'clear')
+ ]
+ end
+ end
+
+ def pagination_sizer_for(scope)
+ return nil if ! scope.first
+ return nil if ! scope.first.class.respond_to? :per_page
+ content_tag(:div, :class => 'pagination') do
+ [content_tag(:span){ "Per page: " }] +
+ [scope.first.class.per_page, 100, :all].map do |n|
+ if (params[:per_page] || scope.per_page.to_s) == n.to_s
+ content_tag(:span, :class => "current"){ n }
+ else
+ link_to(n, {:per_page => n})
+ end
end
end
end
View
9 app/helpers/paginate_scope_helper.rb
@@ -1,7 +1,12 @@
module PaginateScopeHelper
# Return a paginated +scope+.
def paginate_scope(scope, opts={})
- opts.reverse_merge!(:page => params[:page])
- return scope.paginate(opts)
+ if ! params[:per_page]
+ scope.paginate( opts.reverse_merge(:page => params[:page]) )
+ elsif params[:per_page] != "all"
+ scope.paginate( opts.reverse_merge(:page => params[:page], :per_page => params[:per_page]) )
+ else
+ scope
+ end
end
end
View
21 app/models/node.rb
@@ -57,33 +57,22 @@ def self.per_page; 20 end # Pagination
end
}
+ named_scope :reported, :conditions => ["reported_at IS NOT NULL"]
+
# Return nodes that have never reported.
named_scope :unreported, :conditions => {:reported_at => nil}
# Return nodes that haven't reported recently.
named_scope :no_longer_reporting, lambda{{:conditions => ['reported_at < ?', SETTINGS.no_longer_reporting_cutoff.seconds.ago] }}
- def self.count_by_currentness_and_successfulness(currentness, successfulness)
- operator = successfulness ? '!=' : '='
- if currentness
- self.by_currentness_and_successfulness(currentness, successfulness).count
- else
- Report.count_by_sql(["SELECT COUNT(node_id) FROM (SELECT DISTINCT node_id FROM reports WHERE status #{operator} 'failed') as tmp"])
- end
- end
+ named_scope :hidden, :conditions => {:hidden => true}
+
+ named_scope :unhidden, :conditions => {:hidden => false}
def self.label_for_currentness_and_successfulness(currentness, successfulness)
return "#{currentness ? 'Currently' : 'Ever'} #{successfulness ? (currentness ? 'successful' : 'succeeded') : (currentness ? 'failing' : 'failed')}"
end
- def self.count_unreported
- unreported.count
- end
-
- def self.count_no_longer_reporting
- no_longer_reporting.count
- end
-
def self.find_from_inventory_search(search_params)
query_string = search_params.
map {|param| "facts.#{CGI::escape param["fact"]}.#{param["comparator"]}=#{CGI::escape param["value"]}" }.
View
4 app/models/node_class.rb
@@ -34,4 +34,8 @@ def self.find_from_form_names(*names)
def self.find_from_form_ids(*ids)
ids.map{|entry| entry.to_s.split(/[ ,]/)}.flatten.reject(&:blank?).uniq.map{|id| self.find(id)}
end
+
+ def <=>(rhs)
+ self.name <=> rhs.name
+ end
end
View
4 app/models/node_group.rb
@@ -76,4 +76,8 @@ def self.find_from_form_names(*names)
def self.find_from_form_ids(*ids)
ids.map{|entry| entry.to_s.split(/[ ,]/)}.flatten.reject(&:blank?).uniq.map{|id| self.find(id)}
end
+
+ def <=>(rhs)
+ self.name <=> rhs.name
+ end
end
View
2  app/models/timeline_event.rb
@@ -6,7 +6,7 @@ class TimelineEvent < ActiveRecord::Base
named_scope :for_node, lambda { |node| {:conditions =>
[ "(subject_id = :id AND subject_type = :klass) OR (secondary_subject_id = :id AND secondary_subject_type = :klass)",
{:id => node.id, :klass => node.class.name} ] } }
- named_scope :recent, :order => 'created_at DESC', :limit => 10
+ named_scope :recent, :order => 'created_at DESC, id DESC', :limit => 10
def subject_name
subject ? subject.name : "A #{subject_type.downcase}"
View
14 app/views/node_classes/index.html.haml
@@ -14,19 +14,19 @@
-# = check_box_tag "check_all"
%th.name
Name
- %tbody
- - if @node_classes.present?
+ - if @node_classes.present?
+ %tbody
- for node_class in @node_classes
%tr[node_class]
-# %td.check
-# = check_box_tag "check_all"
%td.name
= link_to h(node_class.name), node_class
- - if @node_classes.total_pages > 1
- %tfoot
- %tr
- %td= pagination_for @node_classes
- - else
+ %tfoot
+ %tr
+ %td= pagination_for @node_classes
+ - else
+ %tbody
%tr
%td
= describe_no_matches_for :classes
View
14 app/views/node_groups/index.html.haml
@@ -14,19 +14,19 @@
-# = check_box_tag "check_all"
%th.name
Name
- %tbody
- - if @node_groups.present?
+ - if @node_groups.present?
+ %tbody
- for node_group in @node_groups
%tr[node_group]
-# %td.check
-# = check_box_tag "check_all"
%td.name
= link_to h(node_group.name), node_group
- - if @node_groups.total_pages > 1
- %tfoot
- %tr
- %td= pagination_for @node_groups
- - else
+ %tfoot
+ %tr
+ %td= pagination_for @node_groups
+ - else
+ %tbody
%tr
%td
= describe_no_matches_for :groups
View
27 app/views/nodes/_actions.html.haml
@@ -1,27 +0,0 @@
--# %ul
- -# %li
- -# %button.drop Groups
- -# .dropdown
- -# %ul
- -# - NodeGroup.all.each do |g|
- -# %li
- -# %label
- -# = check_box_tag dom_id(g)
- -# = g.name
- -# .actions
- -# = link_to "Assign"
- -# %li
- -# %button.drop Classes
- -# .dropdown
- -# %ul
- -# - NodeClass.all.each do |c|
- -# %li
- -# %label
- -# = check_box_tag dom_id(c)
- -# = c.name
- -# .actions
- -# = link_to "Assign"
-
-%ul
- %li
- = link_to "Add node", new_node_path, :class => 'button'
View
0  app/views/nodes/_hidden.html.haml
No changes.
View
16 app/views/nodes/_node.html.haml
@@ -1,16 +0,0 @@
-.node[node]
- %h3= link_to node.name, node
- .info
- - unless node.node_classes.empty?
- %h4 Classes:
- %p= node.all_classes.map{|cl| link_to cl.name, cl}.to_sentence
- - unless node.node_groups.empty?
- %h4 Groups:
- %p= node.node_groups.map{|gr| link_to gr.name, gr}.to_sentence
- - unless node.parameters.blank?
- %h4 Parameters:
- = inspector_table node.parameters, :key, :value, :link => false
- .actions
- = link_to "Edit", edit_node_path(node), :class => "edit"
- - unless node.node_classes.empty? && node.node_groups.empty? && node.parameters.blank?
- = link_to "<span class='response'>Show</span> Details", "##{node.id}", :class => "collapsible-trigger"
View
6 app/views/nodes/_nodes.html.haml
@@ -30,7 +30,11 @@
= sources.map{|s| link_to(s.name,s)}.join(", ")
%td.latest_report
= node.last_report ? node.last_report.time : "Has not reported"
- = pagination_for nodes, more_link
- else
%td.empty{:colspan => container.nil? ? 3 : 4}
= describe_no_matches_for :nodes
+ - if nodes.present?
+ %tfoot
+ %tr
+ %td{:colspan => container.nil? ? 3 : 4 }
+ = pagination_for nodes, more_link
View
12 app/views/nodes/show.html.haml
@@ -5,9 +5,15 @@
= node_status_icon(@node)
Node:
= h @node.name
- %ul.actions
- %li= link_to 'Edit', edit_node_path(@node), :class => "edit button", :rel => 'inspect'
- %li= link_to 'Destroy', @node, :confirm => 'Are you sure?', :method => :delete, :class => "delete button"
+ %span.alt= "(hidden)" if @node.hidden
+ - if SETTINGS.use_external_node_classification
+ %ul.actions
+ %li= link_to 'Edit', edit_node_path(@node), :class => "edit button", :rel => 'inspect'
+ - if @node.hidden
+ %li= link_to 'Unhide', unhide_node_path(@node), :class => "hide button", :method => :put
+ - else
+ %li= link_to 'Hide', hide_node_path(@node), :class => "hide button", :method => :put
+ %li= link_to 'Destroy', @node, :confirm => 'Are you sure you wish to destroy this node?', :method => :delete, :class => "delete button"
.item
- unless @node.description.blank?
.description= simple_format h(@node.description)
View
4 app/views/pages/home.html.haml
@@ -33,7 +33,7 @@
= truncated_node_sentence(@unreported_nodes, :more_link => unreported_nodes_path)
.section
- = render 'statuses/run_failure', :statuses => @statuses
+ = render 'statuses/run_failure', :nodes => @unhidden_nodes
.section
%h3 Recently-reported nodes
- = render 'nodes/nodes', :nodes => @nodes, :more_link => nodes_path(:page => 2)
+ = render 'nodes/nodes', :nodes => @recently_reported_nodes, :more_link => nodes_path(:page => 2)
View
2  app/views/shared/_classes.html.haml
@@ -7,7 +7,7 @@
%th.name Class
%th Source
%tbody
- - resource.node_classes_with_sources.sort.each do |node_class,sources|
+ - resource.node_classes_with_sources.each do |node_class,sources|
%tr
%td.name
%strong= link_to(node_class.name,node_class)
View
6 app/views/shared/_global_nav.html.haml
@@ -1,6 +1,10 @@
%ul#global-navigation.navigation
%li
- = link_to "Puppet Dashboard", root_path, :id => "logo"
+ - if SETTINGS.custom_logo_url
+ %a{:href => root_path, :id => "logo", :style => "background-image:none"}
+ %img{:src => SETTINGS.custom_logo_url, :height => '23', :width => '155', :alt => "Puppet Dashboard" }
+ - else
+ %a{:href => root_path, :id => "logo", :style => "text-indent: -9000px;"} Puppet Dashboard
%li{:class => active_if(request.url == release_notes_url)}
= link_to "v#{APP_VERSION}", release_notes_path
%li &raquo;
View
15 app/views/shared/_node_manager_sidebar.html.haml
@@ -1,27 +1,32 @@
.group
%h3{:class => active_if(controller_name == "nodes" && action_name == "index")}= link_to "Nodes", nodes_path
- %span.count= Node.count
+ %span.count= Node.unhidden.count
%ul
- for currentness in [true, false]
- for successfulness in [true, false]
%li{:class => active_if(controller_name == 'nodes' && params[:current] && (params[:current] == "true") == currentness && params[:successful] && (params[:successful] == "true") == successfulness && parent.nil?)}
- label = Node.label_for_currentness_and_successfulness(currentness, successfulness)
= link_to label, nodes_path(:current => currentness.to_s, :successful => successfulness.to_s)
- - count = Node.count_by_currentness_and_successfulness(currentness, successfulness)
+ - count = Node.unhidden.by_currentness_and_successfulness(currentness, successfulness).length
%span.count{:class => counter_class(count, currentness && !successfulness)}= count
%li{:class => active_if(controller_name == 'nodes' && action_name == 'unreported' && parent.nil?)}
= link_to "Never reported", unreported_nodes_path
- - count = Node.count_unreported
+ - count = Node.unreported.unhidden.count
%span.count{:class => counter_class(count, true)}= count
%li{:class => active_if(controller_name == 'nodes' && action_name == 'no_longer_reporting' && parent.nil?)}
= link_to "Not currently reporting", no_longer_reporting_nodes_path
- - count = Node.count_no_longer_reporting
+ - count = Node.no_longer_reporting.unhidden.count
%span.count{:class => counter_class(count, true)}= count
+ %li{:class => active_if(controller_name == 'nodes' && action_name == 'hidden' && parent.nil?)}
+ = link_to "Hidden", hidden_nodes_path
+ - count = Node.hidden.count
+ %span.count{:class => counter_class(count, false)}= count
- if SETTINGS.experimental_inventory_service
%li
= link_to "Custom query", search_nodes_path
.footer.actionbar
- = link_to "Add node", new_node_path, :class => 'button'
+ - if SETTINGS.use_external_node_classification
+ = link_to "Add node", new_node_path, :class => 'button'
- if SETTINGS.use_external_node_classification
- for type in [NodeClass, NodeGroup]
View
2  config/environment.rb
@@ -5,7 +5,7 @@
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
-require 'activesupport'
+require 'active_support'
Rails::Initializer.run do |config|
config.gem 'rack'
View
7 config/routes.rb
@@ -7,15 +7,16 @@
groups.resources :nodes, :requirements => {:id => /.*/}
end
- map.resources :nodes,
+ map.resources :nodes,
:member => {
+ :hide => :put,
+ :unhide => :put,
:facts => :get,
:reports => :get},
:collection => {
- :successful => :get,
- :failed => :get,
:unreported => :get,
:no_longer_reporting => :get,
+ :hidden => :get,
:search => :get},
:requirements => {:id => /[^\/]+/}
View
3  config/settings.yml.example
@@ -53,4 +53,7 @@ use_external_node_classification: true
datetime_format: '%Y-%m-%d %H:%M %Z'
date_format: '%Y-%m-%d'
+# Set this to the URL of an image. The image will be scaled to 155x23 pixels.
+#custom_logo_url: 'http://www.puppetlabs.com/images/puppet-short.png'
+
#===[ fin ]=============================================================
View
9 db/migrate/20101118222325_add_hidden_to_nodes.rb
@@ -0,0 +1,9 @@
+class AddHiddenToNodes < ActiveRecord::Migration
+ def self.up
+ add_column :nodes, :hidden, :boolean, :default => false
+ end
+
+ def self.down
+ remove_column :nodes, :hidden
+ end
+end
View
3  db/schema.rb
@@ -9,7 +9,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20101109001012) do
+ActiveRecord::Schema.define(:version => 20101118222325) do
create_table "assignments", :force => true do |t|
t.integer "node_id"
@@ -67,6 +67,7 @@
t.datetime "reported_at"
t.integer "last_report_id"
t.string "status"
+ t.boolean "hidden", :default => false
end
create_table "parameters", :force => true do |t|
View
2  ext/packaging/debian/changelog
@@ -1,4 +1,4 @@
-puppet-dashboard (1.0.4-1) lucid; urgency=low
+puppet-dashboard (1.0.4-1) intrepid jaunty karmic lucid meerkat narwhal; urgency=low
* 1.0.4-1 maintenance release
View
7 lib/settings_reader.rb
@@ -3,7 +3,7 @@
require 'ostruct'
require 'rubygems'
-require 'activesupport'
+require 'active_support'
# = SettingsReader
#
@@ -45,6 +45,11 @@ def self.read
return OpenStruct.new(settings)
end
+ def self.default_settings
+ rails_root = RAILS_ROOT rescue File.dirname(File.dirname(__FILE__))
+ OpenStruct.new(self.filename_to_hash(File.join(rails_root, "config/settings.yml.example")))
+ end
+
# Return an OpenStruct object by reading the +filename+ and parsing it with ERB and YAML.
def self.filename_to_hash(filename)
return YAML.load(ERB.new(File.read(filename)).result) rescue {}
View
23 lib/tasks/package.rake
@@ -90,6 +90,29 @@ $RPM_BUILD_ROOT %{buildroot}
end
end
+ desc "Create a release .tar.gz"
+ task :tar do
+ version = File.open('VERSION', 'r').read.sub(/^v/, '').chomp
+ work = File.expand_path(File.join(RAILS_ROOT, 'tmp', 'packages', 'tar'))
+ release_prefix = "puppet-dashboard-#{version}"
+ release_file = File.join work, "#{release_prefix}.tar.gz"
+
+ mkdir_p work
+ if File.exists?(release_file)
+ puts <<-HERE
+!! Release tar.gz file already exists: #{release_prefix}.tar.gz
+!! Please move or remove this file before proceeding.
+ HERE
+ raise
+ end
+
+ sh %Q{git archive --format=tar --prefix=#{release_prefix}/ HEAD | gzip > "#{release_file}"}
+
+ puts <<-HERE
+Saved release to: #{release_file}
+ HERE
+ end
+
task :build_environment do
unless ENV['FORCE'] == '1'
modified = `git status --porcelain | sed -e '/^\?/d'`
View
1  public/stylesheets/application.css
@@ -35,7 +35,6 @@ body {
font-weight: bold; }
body #header a#logo {
background: transparent url("../images/dashboard_logo.png") no-repeat top center;
- text-indent: -9000px;
display: inline-block;
height: 23px;
width: 155px;
View
1  public/stylesheets/sass/application.scss
@@ -138,7 +138,6 @@ body {
a#logo {
background: transparent url('../images/dashboard_logo.png') no-repeat top center;
- text-indent: -9000px;
display: inline-block;
height: 23px;
width: 155px;
View
344 spec/controllers/nodes_controller_spec.rb
@@ -143,97 +143,128 @@
end
describe '#edit' do
- before :each do
- @node = Node.generate!
- end
-
def do_get
get :edit, :id => @node.id
end
- it 'should make the requested node available to the view' do
- do_get
- assigns[:node].should == @node
- end
+ describe "when using node classification" do
+ before :each do
+ SETTINGS.stubs(:use_external_node_classification).returns(true)
+ @node = Node.generate!
- it 'should render the edit template' do
- do_get
- response.should render_template('edit')
+ it 'should make the requested node available to the view' do
+ do_get
+ assigns[:node].should == @node
+ end
+
+ it 'should render the edit template' do
+ do_get
+ response.should render_template('edit')
+ end
+
+ it 'should work when given a node name' do
+ get :edit, :id => @node.name
+
+ assigns[:node].should == @node
+ end
+ end
end
- it 'should work when given a node name' do
- get :edit, :id => @node.name
+ describe "when not using node classification" do
+ before :each do
+ SETTINGS.stubs(:use_external_node_classification).returns(false)
+ @node = Node.generate!
+ end
+
+ it 'should render 403 text' do
+ do_get
- assigns[:node].should == @node
+ response.body.should =~ /Node classification has been disabled/
+ response.should_not be_success
+ response.response_code.should == 403
+ end
end
end
describe '#update' do
- before :each do
- @node = Node.generate!
- @params = { :id => @node.id, :node => @node.attributes }
- end
-
def do_put
put :update, @params
end
- it 'should fail when an invalid node id is given' do
- @params[:id] = 'unknown'
- lambda { do_put }.should raise_error(ActiveRecord::RecordNotFound)
- end
+ describe "when using node classification" do
+ before :each do
+ SETTINGS.stubs(:use_external_node_classification).returns(true)
+ @node = Node.generate!
+ @params = { :id => @node.id, :node => @node.attributes }
+ end
- it 'should work when given a node name' do
- @params.merge!({:id => @node.name})
+ it 'should fail when an invalid node id is given' do
+ @params[:id] = 'unknown'
+ lambda { do_put }.should raise_error(ActiveRecord::RecordNotFound)
+ end
- do_put
- assigns[:node].should == @node
- end
+ it 'should work when given a node name' do
+ @params.merge!({:id => @node.name})
- describe 'when a valid node id is given' do
+ do_put
+ assigns[:node].should == @node
+ end
- describe 'and the data provided would make the node invalid' do
- before :each do
- @params[:node]['name'] = nil
- end
+ describe 'when a valid node id is given' do
- it 'should make the node available to the view' do
- do_put
- assigns[:node].should == @node
- end
+ describe 'and the data provided would make the node invalid' do
+ before :each do
+ @params[:node]['name'] = nil
+ end
- it 'should not save the node' do
- do_put
- Node.find(@node.id).name.should_not be_nil
- end
+ it 'should make the node available to the view' do
+ do_put
+ assigns[:node].should == @node
+ end
+
+ it 'should not save the node' do
+ do_put
+ Node.find(@node.id).name.should_not be_nil
+ end
- it 'should have errors on the node' do
- do_put
- assigns[:node].errors[:name].should_not be_blank
+ it 'should have errors on the node' do
+ do_put
+ assigns[:node].errors[:name].should_not be_blank
+ end
+
+ it 'should render the update action' do
+ do_put
+ response.should render_template('edit')
+ end
end
- it 'should render the update action' do
- do_put
- response.should render_template('edit')
+ describe 'and the data provided make the node valid' do
+ it 'should update the node with the data provided' do
+ @params[:node]['name'] = 'new name'
+ do_put
+ Node.find(@node.id).name.should == 'new name'
+ end
+
+ it 'should have a valid node' do
+ do_put
+ assigns[:node].should be_valid
+ end
end
end
+ end
- describe 'and the data provided make the node valid' do
- it 'should note the update success in flash' do
- do_put
- flash[:notice].should match(/success/i)
- end
+ describe "when not using node classification" do
+ before :each do
+ SETTINGS.stubs(:use_external_node_classification).returns(false)
+ @node = Node.generate!
+ end
- it 'should update the node with the data provided' do
- @params[:node]['name'] = 'new name'
- do_put
- Node.find(@node.id).name.should == 'new name'
- end
+ it 'should render 403 text' do
+ do_put
- it 'should have a valid node' do
- do_put
- assigns[:node].should be_valid
- end
+ response.body.should =~ /Node classification has been disabled/
+ response.should_not be_success
+ response.response_code.should == 403
end
end
end
@@ -265,6 +296,32 @@ def do_put
end
end
+ describe "#hide" do
+ it "should hide the node" do
+ @node = Node.generate!
+ @node.hidden.should == false
+
+ put :hide, :id => @node.name
+
+ response.should redirect_to(node_path(@node))
+ @node.reload
+ @node.hidden.should == true
+ end
+ end
+
+ describe "#unhide" do
+ it "should unhide the node" do
+ @node = Node.generate! :hidden => true
+ @node.hidden.should == true
+
+ put :unhide, :id => @node.name
+
+ response.should redirect_to(node_path(@node))
+ @node.reload
+ @node.hidden.should == false
+ end
+ end
+
describe "#facts" do
before :each do
@time = Time.now
@@ -302,22 +359,6 @@ def do_get
end
describe "#reports" do
- shared_examples_for "a successful reports rendering" do
- specify { response.should be_success }
- end
-
- shared_examples_for "a paginated reports collection" do
- it "should be paginated" do
- assigns[:reports].should be_a_kind_of(WillPaginate::Collection)
- end
- end
-
- shared_examples_for "an un-paginated reports collection" do
- it "should not be paginated" do
- assigns[:reports].should_not be_a_kind_of(WillPaginate::Collection)
- end
- end
-
before :each do
@node = Node.generate!
Node.stubs(:find_by_name! => @node)
@@ -329,15 +370,21 @@ def do_get
context "for HTML" do
before { get :reports, :node => 123 }
- it_should_behave_like "a successful reports rendering"
- it_should_behave_like "a paginated reports collection"
+ specify { response.should be_success }
+
+ it "should be paginated" do
+ assigns[:reports].should be_a_kind_of(WillPaginate::Collection)
+ end
end
context "for YAML" do
before { get :reports, :node => 123, :format => "yaml" }
- it_should_behave_like "a successful reports rendering"
- it_should_behave_like "an un-paginated reports collection"
+ specify { response.should be_success }
+
+ it "should not be paginated" do
+ assigns[:reports].should_not be_a_kind_of(WillPaginate::Collection)
+ end
it "should return YAML" do
response.body.should =~ %r{ruby/object:Report}
@@ -350,8 +397,11 @@ def do_get
context "for JSON" do
before { get :reports, :node => 123, :format => "json" }
- it_should_behave_like "a successful reports rendering"
- it_should_behave_like "an un-paginated reports collection"
+ specify { response.should be_success }
+
+ it "should not be paginated" do
+ assigns[:reports].should_not be_a_kind_of(WillPaginate::Collection)
+ end
it "should return JSON" do
struct = json_from_response_body
@@ -375,42 +425,21 @@ def do_get
# Relies on #action returning name of a NodesController action, e.g. as "successful".
describe "#scoped_index" do
- shared_examples_for "a successful scoped_index rendering" do
- specify { response.should be_success }
-
- it "should assign only appropriate records" do
- assigns[:nodes].size.should == 1
- assigns[:nodes].first.name.should == action
- end
- end
-
- shared_examples_for "a paginated nodes collection" do
- it "should be paginated" do
- assigns[:nodes].should be_a_kind_of(WillPaginate::Collection)
- end
- end
-
- shared_examples_for "an un-paginated nodes collection" do
- it "should not be paginated" do
- assigns[:nodes].should_not be_a_kind_of(WillPaginate::Collection)
- end
- end
-
- shared_examples_for "a scope_index action" do
- before :each do
- @results = [Node.generate!(:name => action)]
- @results.stubs(:with_last_report => @results, :by_report_date => @results)
- Node.stubs(action => @results)
- Node.stubs(:by_currentness_and_successfulness => @results)
- end
-
+ shared_examples_for "a scoped_index action" do
context "as HTML" do
before { get action, action_params }
- it_should_behave_like "a successful scoped_index rendering"
+ specify { response.should be_success }
+
+ it "should assign only appropriate records" do
+ assigns[:nodes].size.should == 1
+ assigns[:nodes].first.name.should == "foo"
+ end
+
# NOTE: Once upon a time, these were paginated but were breaking the graphs
- # it_should_behave_like "a paginated nodes collection"
- it_should_behave_like "an un-paginated nodes collection"
+ it "should not be paginated" do
+ assigns[:nodes].should_not be_a_kind_of(WillPaginate::Collection)
+ end
end
context "as YAML" do
@@ -420,13 +449,20 @@ def do_get
get action, action_params.merge(:format => "yaml")
end
- it_should_behave_like "a successful scoped_index rendering"
- it_should_behave_like "an un-paginated nodes collection"
+ specify { response.should be_success }
+
+ it "should assign only appropriate records" do
+ assigns[:nodes].size.should == 1
+ end
+
+ it "should not be paginated" do
+ assigns[:nodes].should_not be_a_kind_of(WillPaginate::Collection)
+ end
it "should return YAML" do
struct = yaml_from_response_body
struct.size.should == 1
- struct.first["name"].should == action
+ struct.first["name"].should == "foo"
end
end
end
@@ -434,25 +470,24 @@ def do_get
context "as JSON" do
before { get action, action_params.merge(:format => "json") }
- it_should_behave_like "a successful scoped_index rendering"
- it_should_behave_like "an un-paginated nodes collection"
+ specify { response.should be_success }
+
+ it "should assign only appropriate records" do
+ assigns[:nodes].size.should == 1
+ end
+
+ it "should not be paginated" do
+ assigns[:nodes].should_not be_a_kind_of(WillPaginate::Collection)
+ end
it "should return JSON" do
struct = json_from_response_body
struct.size.should == 1
- struct.first["name"].should == action
+ struct.first["name"].should == "foo"
end
end
end
- for action in %w[unreported no_longer_reporting]
- describe action do
- let(:action) { action }
- let(:action_params) { {} }
- it_should_behave_like "a scope_index action"
- end
- end
-
describe "#successful" do
it "should redirect to current and successful" do
get :successful
@@ -469,11 +504,58 @@ def do_get
end
end
+ describe "#unreported" do
+ before :each do
+ @node = Node.generate!(:name => "foo")
+ @hidden_node = Node.generate!(:name => "bar", :hidden => true)
+ end
+
+ let(:action) { "unreported" }
+ let(:action_params) { {} }
+
+ it_should_behave_like "a scoped_index action"
+ end
+
+ describe "#no_longer_reporting" do
+ before :each do
+ SETTINGS.stubs(:no_longer_reporting_cutoff).returns(60)
+ @node = Node.generate!(:name => "foo")
+ @hidden_node = Node.generate!(:name => "bar", :hidden => true)
+ Report.generate_for(@node, 1.hour.ago)
+ Report.generate_for(@hidden_node, 1.hour.ago)
+ end
+
+ let(:action) { "no_longer_reporting" }
+ let(:action_params) { {} }
+
+ it_should_behave_like "a scoped_index action"
+ end
+
+ describe "#hidden" do
+ before :each do
+ @node = Node.generate!(:name => "foo", :hidden => true)
+ @unhidden_node = Node.generate!(:name => "bar")
+ end
+
+ let(:action) { "hidden" }
+ let(:action_params) { {} }
+
+ it_should_behave_like "a scoped_index action"
+ end
+
describe "current and successful" do
+ before :each do
+ SETTINGS.stubs(:no_longer_reporting_cutoff).returns(3600)
+ @node = Node.generate!(:name => "foo")
+ @hidden_node = Node.generate!(:name => "bar", :hidden => true)
+ Report.generate_for(@node, 5.minutes.ago, "unchanged")
+ Report.generate_for(@hidden_node, 5.minutes.ago, "unchanged")
+ end
+
let(:action) { "index" }
- let(:action_params) { {:current => true, :successful => true} }
+ let(:action_params) { {:current => "true", :successful => "true"} }
- it_should_behave_like "a scope_index action"
+ it_should_behave_like "a scoped_index action"
end
end
end
View
26 spec/controllers/pages_controller_spec.rb
@@ -1,4 +1,30 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe PagesController do
+ describe "#home" do
+ before :each do
+ SETTINGS.stubs(:no_longer_reporting_cutoff).returns(3600)
+
+ @currently_failing_node = Node.generate!(:name => "currently_failing")
+ @unreported_node = Node.generate!(:name => "unreported")
+ @no_longer_reporting_node = Node.generate!(:name => "no_longer_reporting")
+ @hidden_node = Node.generate!(:name => "hidden", :hidden => true)
+ @unreported_hidden_node = Node.generate!(:name => "unreported_hidden", :hidden => true)
+ @no_longer_reporting_hidden_node = Node.generate!(:name => "no_longer_reporting_hidden", :hidden => true)
+ Report.generate_for(@currently_failing_node, 5.minutes.ago, "failed")
+ Report.generate_for(@no_longer_reporting_node, 2.hours.ago, "unchanged")
+ Report.generate_for(@hidden_node, 5.minutes.ago, "failed")
+ Report.generate_for(@no_longer_reporting_hidden_node, 2.hours.ago, "failed")
+ end
+
+ it "should properly categorize nodes" do
+ get :home
+
+ assigns[:currently_failing_nodes].map(&:name).should =~ ["currently_failing"]
+ assigns[:unreported_nodes].map(&:name).should =~ ["unreported"]
+ assigns[:no_longer_reporting_nodes].map(&:name).should =~ ["no_longer_reporting"]
+ assigns[:recently_reported_nodes].map(&:name).should =~ ["currently_failing", "no_longer_reporting"]
+ assigns[:unhidden_nodes].map(&:name).should =~ ["currently_failing", "unreported", "no_longer_reporting"]
+ end
+ end
end
View
32 spec/helpers/application_helper_spec.rb
@@ -61,7 +61,37 @@
context "when not given paginated records" do
subject { helper.pagination_for([]) }
- it { should be_nil }
+ it { should have_tag('div.actionbar') }
+ it { should_not have_tag('a', /Next/) }
+ end
+
+ describe "when rendering the page size control" do
+ it "should use the default per_page setting" do
+ foo = Class.new do
+ def self.per_page; 51 ; end
+ end
+ paginated_results = [foo.new].paginate
+ helper.pagination_for(paginated_results).should have_tag('a', /51/)
+ end
+
+ it "should render spans instead of links for the current pagination size" do
+ foo = Class.new do
+ def self.per_page; 51 ; end
+ end
+ paginated_results = [foo.new].paginate(:per_page => 100)
+ helper.pagination_for(paginated_results).should have_tag('span', /100/)
+ end
+
+ it "should render spans instead of links for the current pagination size supplied in the url" do
+ foo = Class.new do
+ def self.per_page; 51 ; end
+ end
+ params[:per_page] = "all"
+ paginated_results = [foo.new]
+ helper.pagination_for(paginated_results).should have_tag('span', /all/)
+ end
+
+
end
end
View
10 spec/helpers/paginate_scope_helper_spec.rb
@@ -5,5 +5,15 @@
it "should paginate the scope" do
helper.paginate_scope([1,2,3]).should be_a_kind_of(WillPaginate::Collection)
end
+
+ it "should pass in the per_page parameter" do
+ params[:per_page] = 2
+ helper.paginate_scope([1,2,3]).per_page.should == 2
+ end
+
+ it "should not paginate if the per_page parameter is 'all'" do
+ params[:per_page] = 'all'
+ helper.paginate_scope([1,2,3]).should_not be_a_kind_of(WillPaginate::Collection)
+ end
end
end
View
82 spec/models/node_spec.rb
@@ -78,12 +78,6 @@
Node.by_currentness_and_successfulness(currentness, successfulness).map(&:name).sort.should == inclusions.sort
end
end
-
- describe "::count_by_currentness_and_successfulness" do
- it "should count the expected nodes" do
- Node.count_by_currentness_and_successfulness(currentness, successfulness).should == inclusions.size
- end
- end
end
end
end
@@ -111,57 +105,23 @@
end
end
- # describe ".successful" do
- # include DescribeReports
-
- # it "should return all nodes whose latest report was successful" do
- # report = Report.generate
- # report.update_attribute(:success, true)
-
- # Node.successful.should include(report.node)
- # end
-
- # it "should not return failed nodes" do
- # successful_report = report_model_from_yaml('success.yml')
- # successful_report.save!
- # successful_node = successful_report.node
-
- # failed_report = report_model_from_yaml('failure.yml')
- # failed_report.save!
- # failed_node = failed_report.node
-
- # Node.successful.should_not include(failed_report.node)
- # end
- # end
-
- # describe ".failed" do
- # include DescribeReports
-
- # it "should return all nodes whose latest report failed" do
- # report = Report.generate
- # report.update_attribute(:success, false)
-
- # Node.failed.should include(report.node)
- # end
+ describe ".reported" do
+ it "should return all nodes with a latest report" do
+ unreported_node = Node.generate
+ reported_node = Node.generate
+ Report.generate_for(reported_node)
- # it "should not return successful nodes" do
- # successful_report = report_model_from_yaml('success.yml')
- # successful_report.save!
- # successful_node = successful_report.node
-
- # failed_report = report_model_from_yaml('failure.yml')
- # failed_report.save!
- # failed_node = failed_report.node
-
- # Node.failed.should_not include(successful_report.node)
- # end
- # end
+ Node.reported.should == [reported_node]
+ end
+ end
describe ".unreported" do
it "should return all nodes whose latest report was unreported" do
- node = Node.generate
+ unreported_node = Node.generate
+ reported_node = Node.generate
+ Report.generate_for(reported_node)
- Node.unreported.should include(node)
+ Node.unreported.should == [unreported_node]
end
end
@@ -176,8 +136,22 @@
end
end
- it 'should be able to compute a configuration' do
- Node.new.should respond_to(:configuration)
+ describe "" do
+ before :each do
+ @nodes = {:hidden => Node.generate!(:hidden => true),
+ :unhidden => Node.generate!(:hidden => false)
+ }
+ end
+
+ [:hidden, :unhidden].each do |hiddenness|
+ describe hiddenness do
+ it "should find all #{hiddenness} nodes" do
+ nodes = Node.send(hiddenness)
+ nodes.length.should == 1
+ nodes.first.should == @nodes[hiddenness]
+ end
+ end
+ end
end
describe 'when computing a configuration' do
View
6 spec/shared_behaviors/controller_mixins.rb
@@ -4,6 +4,7 @@
describe "with search by q and tag", :shared => true do
describe "when searching" do
before :each do
+ SETTINGS.stubs(:use_external_node_classification).returns(true)
@for_tag = model.generate(:name => 'for_tag')
@for_q = model.generate(:name => 'for_q')
model.generate(:name => 'without_search')
@@ -50,7 +51,10 @@
describe "without JSON pagination" do
describe "GET index" do
describe "as HTML" do
- before { get 'index', :format => 'html' }
+ before do
+ SETTINGS.stubs(:use_external_node_classification).returns(true)
+ get 'index', :format => 'html'
+ end
subject { assigns[model.name.tableize] }
# NOTE: Once upon a time, the collection was paginated until it was realized that this broke the charts.
View
6 spec/spec_helper.rb
@@ -15,4 +15,10 @@
Spec::Runner.configure do |config|
config.mock_with :mocha
+ config.prepend_before :each do
+ verbosity = $VERBOSE
+ $VERBOSE = nil
+ SETTINGS = SettingsReader.default_settings
+ $VERBOSE = verbosity
+ end
end
View
12 spec/views/nodes/_actions.html.haml_spec.rb
@@ -1,12 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
-
-describe "/nodes/_actions.html.haml" do
- include NodesHelper
-
- describe "successful render" do
- before { render }
-
- specify { response.should be_success }
- it { should have_tag('a[href=?]', new_node_path) }
- end
-end
View
16 spec/views/nodes/_node.html.haml_spec.rb
@@ -1,16 +0,0 @@
-require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
-
-describe "/nodes/_node.html.haml" do
- include NodesHelper
-
- describe "successful render" do
- before :each do
- @node = Node.generate!
- render :locals => {:node => @node}
- end
-
- specify { response.should be_a_success }
- it { should have_tag(".node#node_#{@node.id}") }
- it { should have_tag('h3', @node.name) }
- end
-end
Please sign in to comment.
Something went wrong with that request. Please try again.