Paired-With: Max Martin
Reviewed-By: Jacob Helwig
Signed-off-by: Nick Lewis <[email protected]>
---
.../indirector/facts/inventory_active_record.rb | 34 +++++++++++++
lib/puppet/rails/inventory_host.rb | 26 ++++++++++
.../facts/inventory_active_record_spec.rb | 52 ++++++++++++++++++++
3 files changed, 112 insertions(+), 0 deletions(-)
diff --git a/lib/puppet/indirector/facts/inventory_active_record.rb
b/lib/puppet/indirector/facts/inventory_active_record.rb
index 6cd63ab..30cb88e 100644
--- a/lib/puppet/indirector/facts/inventory_active_record.rb
+++ b/lib/puppet/indirector/facts/inventory_active_record.rb
@@ -30,4 +30,38 @@ class Puppet::Node::Facts::InventoryActiveRecord <
Puppet::Indirector::ActiveRec
host.save
end
end
+
+ def search(request)
+ return [] unless request.options
+ fact_names = []
+ filters = Hash.new {|h,k| h[k] = []}
+ request.options.each do |key,value|
+ type, name, operator = key.to_s.split(".")
+ operator ||= "eq"
+ filters[operator] << [name,value]
+ end
+
+
+ host_sets = []
+ filters['eq'].each do |name,value|
+ host_sets <<
Puppet::Rails::InventoryHost.has_fact_with_value(name,value).map {|host|
host.name}
+ end
+ filters['ne'].each do |name,value|
+ host_sets <<
Puppet::Rails::InventoryHost.has_fact_without_value(name,value).map {|host|
host.name}
+ end
+ {
+ 'gt' => '>',
+ 'lt' => '<',
+ 'ge' => '>=',
+ 'le' => '<='
+ }.each do |operator_name,operator|
+ filters[operator_name].each do |name,value|
+ hosts_with_fact = Puppet::Rails::InventoryHost.has_fact(name)
+ host_sets << hosts_with_fact.select {|h|
h.value_for(name).to_f.send(operator, value.to_f)}.map {|host| host.name}
+ end
+ end
+
+ # to_a because [].inject == nil
+ host_sets.inject {|hosts,this_set| hosts & this_set}.to_a
+ end
end
diff --git a/lib/puppet/rails/inventory_host.rb
b/lib/puppet/rails/inventory_host.rb
index 433e543..10dd620 100644
--- a/lib/puppet/rails/inventory_host.rb
+++ b/lib/puppet/rails/inventory_host.rb
@@ -3,6 +3,32 @@ require 'puppet/rails/inventory_fact'
class Puppet::Rails::InventoryHost < ::ActiveRecord::Base
has_many :facts, :class_name => "Puppet::Rails::InventoryFact", :dependent
=> :delete_all
+ named_scope :has_fact_with_value, lambda { |name,value|
+ {
+ :conditions => ["inventory_facts.name = ? AND inventory_facts.value =
?", name, value],
+ :joins => :facts
+ }
+ }
+
+ named_scope :has_fact_without_value, lambda { |name,value|
+ {
+ :conditions => ["inventory_facts.name = ? AND inventory_facts.value !=
?", name, value],
+ :joins => :facts
+ }
+ }
+
+ named_scope :has_fact, lambda { |name|
+ {
+ :conditions => ["inventory_facts.name = ?", name],
+ :joins => :facts
+ }
+ }
+
+ def value_for(fact_name)
+ fact = facts.find_by_name(fact_name)
+ fact ? fact.value : nil
+ end
+
def facts_to_hash
facts.inject({}) do |fact_hash,fact|
fact_hash.merge(fact.name => fact.value)
diff --git a/spec/unit/indirector/facts/inventory_active_record_spec.rb
b/spec/unit/indirector/facts/inventory_active_record_spec.rb
index b97bada..7fb5556 100644
--- a/spec/unit/indirector/facts/inventory_active_record_spec.rb
+++ b/spec/unit/indirector/facts/inventory_active_record_spec.rb
@@ -95,5 +95,57 @@ describe "Puppet::Node::Facts::InventoryActiveRecord", :if
=> (Puppet.features.r
Puppet::Node::Facts.find("array").values["fact1"].should == "value1"
end
end
+
+ describe "#search" do
+
+ it "should return node names that match 'equal' constraints" do
+ Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2",
"fact3" => "value3").save
+ Puppet::Node::Facts.new("bar", "fact1" => "value2").save
+ Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1",
"fact3" => "value1").save
+
+ request = Puppet::Indirector::Request.new(:facts, :search, nil,
+ {'facts.fact1.eq' => 'value1',
+ 'facts.fact2.eq' => 'value2',
+ 'facts.fact3.eq' => 'value3'})
+ terminus.search(request).should =~ ["foo"]
+ end
+
+ it "should return node names that match 'not equal' constraints" do
+ Puppet::Node::Facts.new("foo", "fact1" => "value1", "fact2" => "value2",
"fact3" => "value3").save
+ Puppet::Node::Facts.new("bar", "fact1" => "value2").save
+ Puppet::Node::Facts.new("baz", "fact1" => "value1", "fact2" => "value1",
"fact3" => "value1").save
+ Puppet::Node::Facts.new("bang", "fact1" => "value1", "fact2" =>
"value2", "fact3" => "value1").save
+
+ request = Puppet::Indirector::Request.new(:facts, :search, nil,
+ {'facts.fact1.ne' => 'value3',
+ 'facts.fact2.ne' => 'value1',
+ 'facts.fact3.ne' => 'value2'})
+ terminus.search(request).should =~ ["foo","bang"]
+ end
+
+ it "should return node names that match strict inequality constraints" do
+ Puppet::Node::Facts.new("foo", "uptime_days" => "30").save
+ Puppet::Node::Facts.new("bar", "uptime_days" => "60").save
+ Puppet::Node::Facts.new("baz", "uptime_days" => "90").save
+
+ request = Puppet::Indirector::Request.new(:facts, :search, nil,
+ {'facts.uptime_days.gt' =>
'20',
+ 'facts.uptime_days.lt' =>
'70'})
+
+ terminus.search(request).should =~ ["foo","bar"]
+ end
+
+ it "should return node names that match non-strict inequality constraints"
do
+ Puppet::Node::Facts.new("foo", "uptime_days" => "30").save
+ Puppet::Node::Facts.new("bar", "uptime_days" => "60").save
+ Puppet::Node::Facts.new("baz", "uptime_days" => "90").save
+
+ request = Puppet::Indirector::Request.new(:facts, :search, nil,
+ {'facts.uptime_days.ge' =>
'30',
+ 'facts.uptime_days.le' =>
'60'})
+
+ terminus.search(request).should =~ ["foo","bar"]
+ end
+ end
end
--
1.7.4.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.