In support of the node status summary change, it is valuable for us to have
a few named scopes that we can easily compose. To that end, we've refactored
the pending scope to take a boolean predicate, and introduced two new scopes
('current' and 'successful'). While these scopes bear only passing resemblance
to the existing concepts with those names, we are moving towards these
semantics overall.
Paired-With: Nick Lewis
Signed-off-by: Pieter van de Bruggen <[email protected]>
---
Local-branch: tickets/next/6991
app/models/node.rb | 35 ++++++++++++++++++----
spec/factories.rb | 59 +++++++++++++++++++++++++++++++++++--
spec/models/node_spec.rb | 72 +++++++++++++++++++++++++++++++++++++++-------
3 files changed, 145 insertions(+), 21 deletions(-)
diff --git a/app/models/node.rb b/app/models/node.rb
index e8cedb4..4d58ac5 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -33,6 +33,21 @@ class Node < ActiveRecord::Base
fires :updated, :on => :update
fires :removed, :on => :destroy
+ named_scope :current, lambda { |predicate|
+ predicate = predicate ? '' : 'NOT'
+ {
+ :conditions => [
+ "#{predicate} (last_apply_report_id IS NOT NULL AND reported_at >= ?)",
+ SETTINGS.no_longer_reporting_cutoff.seconds.ago
+ ]
+ }
+ }
+
+ named_scope :successful, lambda { |predicate|
+ predicate = predicate ? '' : 'NOT'
+ { :conditions => [ "#{predicate} (nodes.status != 'failed')" ] }
+ }
+
# Return nodes based on their currentness and successfulness.
#
# The terms are:
@@ -59,12 +74,20 @@ class Node < ActiveRecord::Base
end
}
- named_scope :pending,
- :conditions => ["resource_events.status = 'noop' and reports.status !=
'failed'"],
- :joins => "join reports on nodes.last_apply_report_id = reports.id
- join resource_statuses on resource_statuses.report_id = reports.id
- join resource_events on resource_events.resource_status_id =
resource_statuses.id",
- :group => 'nodes.id'
+ named_scope :pending, lambda { |predicate|
+ predicate = predicate ? '' : 'NOT'
+ {
+ :conditions => <<-SQL
+ nodes.id #{predicate} IN (
+ SELECT nodes.id FROM nodes
+ INNER JOIN reports ON nodes.last_apply_report_id = reports.id
+ INNER JOIN resource_statuses ON reports.id =
resource_statuses.report_id
+ INNER JOIN resource_events ON resource_statuses.id =
resource_events.resource_status_id
+ WHERE resource_events.status = 'noop'
+ )
+ SQL
+ }
+ }
named_scope :reported, :conditions => ["reported_at IS NOT NULL"]
diff --git a/spec/factories.rb b/spec/factories.rb
index 2d4e374..178c786 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -11,10 +11,6 @@ Factory.define :parameter do |parameter|
parameter.sequence(:value) {|n| "Value #{n}" }
end
-Factory.define :node do |node|
- node.name { Factory.next(:name) }
-end
-
Factory.define :report do |report|
report.status "failed"
report.kind "apply"
@@ -28,6 +24,10 @@ Factory.define :report do |report|
report.time { Factory.next(:time) }
end
+Factory.define :failing_report, :parent => :report do |report|
+ report.status 'failed'
+end
+
Factory.define :inspect_report, :parent => :report do |inspect|
inspect.kind 'inspect'
end
@@ -38,6 +38,57 @@ end
Factory.define :resource_event do |event|
end
+Factory.define :node do |node|
+ node.name { Factory.next(:name) }
+end
+
+Factory.define :reported_node, :parent => :node do |node|
+ node.after_create do |node|
+ Report.generate!(:host => node.name)
+ node.reload
+ end
+end
+
+Factory.define :unresponsive_node, :parent => :reported_node do |node|
+ node.after_create do |node|
+ node.last_apply_report.update_attributes!(:time => 2.days.ago)
+ node.update_attributes!(:reported_at => 2.days.ago)
+ end
+end
+
+Factory.define :current_node, :parent => :reported_node do |node|
+ node.after_create do |node|
+ node.last_apply_report.update_attributes!(:time => 2.minutes.ago)
+ node.update_attributes!(:reported_at => 2.minutes.ago)
+ end
+end
+
+Factory.define :failing_node, :parent => :current_node do |node|
+ node.after_create do |node|
+ node.last_apply_report.update_attributes!(:status => 'failed')
+ node.update_attributes!(:status => 'failed')
+ end
+end
+
+Factory.define :successful_node, :parent => :current_node do |node|
+ node.after_create do |node|
+ node.last_apply_report.update_attributes!(:status => 'changed')
+ node.update_attributes!(:status => 'changed')
+ end
+end
+
+Factory.define :pending_node, :parent => :successful_node do |node|
+ node.after_create do |node|
+
node.last_apply_report.resource_statuses.generate().events.generate(:status =>
'noop')
+ end
+end
+
+Factory.define :compliant_node, :parent => :successful_node do |node|
+ node.after_create do |node|
+
node.last_apply_report.resource_statuses.generate().events.generate(:status =>
'success')
+ end
+end
+
Factory.sequence :name do |n|
"name_#{n}"
end
diff --git a/spec/models/node_spec.rb b/spec/models/node_spec.rb
index 90a96df..f47d51e 100644
--- a/spec/models/node_spec.rb
+++ b/spec/models/node_spec.rb
@@ -89,25 +89,75 @@ describe Node do
describe "::pending" do
before :each do
- @node = Node.generate!
- @report = Report.generate!(:status => "unchanged", :host => @node.name)
+ @pending = Node.generate!
+ @report = Report.generate!(:status => "unchanged", :host =>
@pending.name)
@resource_status = @report.resource_statuses.generate!(:resource_type =>
"file", :title => "/tmp/foo", :failed => false)
@resource_status.events.generate!(:status => "noop")
+ @resource_status.events.generate!(:status => "success")
+
+ @current = Node.generate!
+ @report = Report.generate!(:status => "unchanged", :host =>
@current.name)
+ @resource_status = @report.resource_statuses.generate!(:resource_type =>
"file", :title => "/tmp/foo", :failed => false)
+ @resource_status.events.generate!(:status => "success")
+ end
+
+ describe "(true)" do
+ it "should find nodes with noop events" do
+ Node.pending(true).should == [@pending]
+ end
+
+ it "should only consider the latest report for a node" do
+ @new_report = Report.generate!(:status => "unchanged", :host =>
@pending.name)
+ Node.pending(true).should == []
+ end
+ end
+
+ describe "(false)" do
+ it "should find nodes without noop events" do
+ Node.pending(false).should == [@current]
+ end
+
+ it "should only consider the latest report for a node" do
+ @new_report = Report.generate!(:status => "unchanged", :host =>
@pending.name)
+ Node.pending(false).should =~ [@pending, @current]
+ end
+ end
+ end
+ describe "::current" do
+ before :each do
+ Factory(:unresponsive_node, :name => 'unresponsive')
+ Factory(:current_node, :name => 'current')
end
- it "should find nodes with noop events" do
- Node.pending.should == [@node]
+ describe "(true)" do
+ it "should find nodes with recent reports" do
+ Node.current(true).map(&:name).should == %w[ current ]
+ end
end
- it "should exclude nodes which are failed" do
- @report.status = 'failed'
- @report.save
- Node.pending.should == []
+ describe "(false)" do
+ it "should find nodes without recent reports" do
+ Node.current(false).map(&:name).should == %w[ unresponsive ]
+ end
end
+ end
- it "should only consider the latest report for a node" do
- @new_report = Report.generate!(:status => "unchanged", :host =>
@node.name)
- Node.pending.should == []
+ describe "::successful" do
+ before :each do
+ Factory(:successful_node, :name => 'successful')
+ Factory(:failing_node, :name => 'failed')
+ end
+
+ describe "(true)" do
+ it "should find nodes with non-failed status" do
+ Node.successful(true).map(&:name).should == %w[ successful ]
+ end
+ end
+
+ describe "(false)" do
+ it "should find nodes with failed status" do
+ Node.successful(false).map(&:name).should == %w[ failed ]
+ end
end
end
--
1.7.5.1
--
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en.