summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Berry <paul@puppetlabs.com>2011-02-17 15:37:12 -0800
committerPaul Berry <paul@puppetlabs.com>2011-02-17 15:37:26 -0800
commit6d5f1aa75c8c64033b56f49e87fc03258d5c158c (patch)
tree13280ce802707d5a8d52e2d7a06d5ab2610d496d
parentab27da7967e1e145d5fbc130e5fbcec6795ca775 (diff)
parent8a485608e2941ff8c7ecc706c21f906d59302dd6 (diff)
downloadpuppet-6d5f1aa75c8c64033b56f49e87fc03258d5c158c.tar.gz
puppet-6d5f1aa75c8c64033b56f49e87fc03258d5c158c.tar.xz
puppet-6d5f1aa75c8c64033b56f49e87fc03258d5c158c.zip
Merge branch 'ticket/2.6.next/6338' into 2.6.next
* ticket/2.6.next/6338: (#5150) Make fact REST terminus configurable to connect to inventory service (#5166) Inventory service is now searchable by timestamp. Maint: backport timestamp accessor for facts from 2.7 branch Refactored Puppet::Node::Inventory::Yaml tests in preparation for adding freshness check Refactor Puppet::Node::Inventory::Yaml in preparation for adding freshness (#5132) Provide a query REST interface for inventory
-rw-r--r--lib/puppet/defaults.rb20
-rw-r--r--lib/puppet/indirector/facts/rest.rb2
-rw-r--r--lib/puppet/indirector/indirection.rb1
-rw-r--r--lib/puppet/indirector/inventory/yaml.rb81
-rw-r--r--lib/puppet/network/http/api/v1.rb3
-rw-r--r--lib/puppet/network/http/handler.rb2
-rw-r--r--lib/puppet/node.rb1
-rwxr-xr-xlib/puppet/node/facts.rb8
-rw-r--r--lib/puppet/node/inventory.rb7
-rwxr-xr-xspec/unit/indirector/facts/yaml_spec.rb4
-rw-r--r--spec/unit/indirector/inventory/yaml_spec.rb221
-rw-r--r--spec/unit/network/http/api/v1_spec.rb12
-rwxr-xr-xspec/unit/network/http/handler_spec.rb11
13 files changed, 362 insertions, 11 deletions
diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb
index 687ac4eb0..8da104086 100644
--- a/lib/puppet/defaults.rb
+++ b/lib/puppet/defaults.rb
@@ -119,7 +119,17 @@ module Puppet
:node_terminus => ["plain", "Where to find information about nodes."],
:catalog_terminus => ["compiler", "Where to get node catalogs. This is useful to change if, for instance,
you'd like to pre-compile catalogs and store them in memcached or some other easily-accessed store."],
- :facts_terminus => [Puppet.application_name.to_s == "master" ? 'yaml' : 'facter', "The node facts terminus."],
+ :facts_terminus => {
+ :default => Puppet.application_name.to_s == "master" ? 'yaml' : 'facter',
+ :desc => "The node facts terminus.",
+ :hook => proc do |value|
+ require 'puppet/node/facts'
+ if value.to_s == "rest"
+ Puppet::Node::Facts.cache_class = :yaml
+ end
+ end
+ },
+ :inventory_terminus => [ "$facts_terminus", "Should usually be the same as the facts terminus" ],
:httplog => { :default => "$logdir/http.log",
:owner => "root",
:mode => 0640,
@@ -582,11 +592,17 @@ module Puppet
end
},
:report_server => ["$server",
- "The server to which to send transaction reports."
+ "The server to send transaction reports to."
],
:report_port => ["$masterport",
"The port to communicate with the report_server."
],
+ :inventory_server => ["$server",
+ "The server to send facts to."
+ ],
+ :inventory_port => ["$masterport",
+ "The port to communicate with the inventory_server."
+ ],
:report => [false,
"Whether to send reports after every transaction."
],
diff --git a/lib/puppet/indirector/facts/rest.rb b/lib/puppet/indirector/facts/rest.rb
index 07491fc77..e2afa14b2 100644
--- a/lib/puppet/indirector/facts/rest.rb
+++ b/lib/puppet/indirector/facts/rest.rb
@@ -3,4 +3,6 @@ require 'puppet/indirector/rest'
class Puppet::Node::Facts::Rest < Puppet::Indirector::REST
desc "Find and save facts about nodes over HTTP via REST."
+ use_server_setting(:inventory_server)
+ use_port_setting(:inventory_port)
end
diff --git a/lib/puppet/indirector/indirection.rb b/lib/puppet/indirector/indirection.rb
index ec147ec69..3d17e6e47 100644
--- a/lib/puppet/indirector/indirection.rb
+++ b/lib/puppet/indirector/indirection.rb
@@ -248,6 +248,7 @@ class Puppet::Indirector::Indirection
if result = terminus.search(request)
raise Puppet::DevError, "Search results from terminus #{terminus.name} are not an array" unless result.is_a?(Array)
result.each do |instance|
+ next unless instance.respond_to? :expiration
instance.expiration ||= self.expiration
end
return result
diff --git a/lib/puppet/indirector/inventory/yaml.rb b/lib/puppet/indirector/inventory/yaml.rb
new file mode 100644
index 000000000..fe3489a95
--- /dev/null
+++ b/lib/puppet/indirector/inventory/yaml.rb
@@ -0,0 +1,81 @@
+require 'puppet/node/inventory'
+require 'puppet/indirector/yaml'
+
+class Puppet::Node::Inventory::Yaml < Puppet::Indirector::Yaml
+ desc "Return node names matching the fact query"
+
+ # Return the path to a given node's file.
+ def yaml_dir_path
+ base = Puppet.run_mode.master? ? Puppet[:yamldir] : Puppet[:clientyamldir]
+ File.join(base, 'facts', '*.yaml')
+ end
+
+ def node_matches?(facts, options)
+ options.each do |key, value|
+ type, name, operator = key.to_s.split(".")
+ operator ||= 'eq'
+
+ return false unless node_matches_option?(type, name, operator, value, facts)
+ end
+ return true
+ end
+
+ def search(request)
+ node_names = []
+ Dir.glob(yaml_dir_path).each do |file|
+ facts = YAML.load_file(file)
+ node_names << facts.name if node_matches?(facts, request.options)
+ end
+ node_names
+ end
+
+ private
+
+ def node_matches_option?(type, name, operator, value, facts)
+ case type
+ when "meta"
+ case name
+ when "timestamp"
+ compare_timestamp(operator, facts.timestamp, Time.parse(value))
+ end
+ when "facts"
+ compare_facts(operator, facts.values[name], value)
+ end
+ end
+
+ def compare_facts(operator, value1, value2)
+ return false unless value1
+
+ case operator
+ when "eq"
+ value1.to_s == value2.to_s
+ when "le"
+ value1.to_f <= value2.to_f
+ when "ge"
+ value1.to_f >= value2.to_f
+ when "lt"
+ value1.to_f < value2.to_f
+ when "gt"
+ value1.to_f > value2.to_f
+ when "ne"
+ value1.to_s != value2.to_s
+ end
+ end
+
+ def compare_timestamp(operator, value1, value2)
+ case operator
+ when "eq"
+ value1 == value2
+ when "le"
+ value1 <= value2
+ when "ge"
+ value1 >= value2
+ when "lt"
+ value1 < value2
+ when "gt"
+ value1 > value2
+ when "ne"
+ value1 != value2
+ end
+ end
+end
diff --git a/lib/puppet/network/http/api/v1.rb b/lib/puppet/network/http/api/v1.rb
index 8aa1f0ee1..0a04a465f 100644
--- a/lib/puppet/network/http/api/v1.rb
+++ b/lib/puppet/network/http/api/v1.rb
@@ -60,9 +60,8 @@ module Puppet::Network::HTTP::API::V1
# fix to not need this, and our goal is to move away from the complication
# that leads to the fix being too long.
return :singular if indirection == "facts"
-
- # "status" really is singular
return :singular if indirection == "status"
+ return :plural if indirection == "inventory"
result = (indirection =~ /s$/) ? :plural : :singular
diff --git a/lib/puppet/network/http/handler.rb b/lib/puppet/network/http/handler.rb
index 9e9356b2f..e192613ad 100644
--- a/lib/puppet/network/http/handler.rb
+++ b/lib/puppet/network/http/handler.rb
@@ -131,7 +131,7 @@ module Puppet::Network::HTTP::Handler
def do_search(indirection_request, request, response)
result = indirection_request.model.search(indirection_request.key, indirection_request.to_hash)
- if result.nil? or (result.is_a?(Array) and result.empty?)
+ if result.nil?
return do_exception(response, "Could not find instances in #{indirection_request.indirection_name} with '#{indirection_request.key}'", 404)
end
diff --git a/lib/puppet/node.rb b/lib/puppet/node.rb
index 2453cd1d5..e8d58e6be 100644
--- a/lib/puppet/node.rb
+++ b/lib/puppet/node.rb
@@ -3,6 +3,7 @@ require 'puppet/indirector'
# A class for managing nodes, including their facts and environment.
class Puppet::Node
require 'puppet/node/facts'
+ require 'puppet/node/inventory'
require 'puppet/node/environment'
# Set up indirection, so that nodes can be looked for in
diff --git a/lib/puppet/node/facts.rb b/lib/puppet/node/facts.rb
index b77ad22d5..562690026 100755
--- a/lib/puppet/node/facts.rb
+++ b/lib/puppet/node/facts.rb
@@ -54,6 +54,14 @@ class Puppet::Node::Facts
strip_internal == other.send(:strip_internal)
end
+ def timestamp=(time)
+ self.values[:_timestamp] = time
+ end
+
+ def timestamp
+ self.values[:_timestamp]
+ end
+
private
# Add internal data to the facts for storage.
diff --git a/lib/puppet/node/inventory.rb b/lib/puppet/node/inventory.rb
new file mode 100644
index 000000000..fd99163b0
--- /dev/null
+++ b/lib/puppet/node/inventory.rb
@@ -0,0 +1,7 @@
+require 'puppet/node'
+require 'puppet/indirector'
+
+class Puppet::Node::Inventory
+ extend Puppet::Indirector
+ indirects :inventory, :terminus_setting => :inventory_terminus
+end
diff --git a/spec/unit/indirector/facts/yaml_spec.rb b/spec/unit/indirector/facts/yaml_spec.rb
index e7bac3471..37a1bcae0 100755
--- a/spec/unit/indirector/facts/yaml_spec.rb
+++ b/spec/unit/indirector/facts/yaml_spec.rb
@@ -10,9 +10,9 @@ describe Puppet::Node::Facts::Yaml do
Puppet::Node::Facts::Yaml.superclass.should equal(Puppet::Indirector::Yaml)
end
-
it "should have documentation" do
Puppet::Node::Facts::Yaml.doc.should_not be_nil
+ Puppet::Node::Facts::Yaml.doc.should_not be_empty
end
it "should be registered with the facts indirection" do
@@ -20,7 +20,7 @@ describe Puppet::Node::Facts::Yaml do
Puppet::Node::Facts::Yaml.indirection.should equal(indirection)
end
- it "should have its name set to :facts" do
+ it "should have its name set to :yaml" do
Puppet::Node::Facts::Yaml.name.should == :yaml
end
end
diff --git a/spec/unit/indirector/inventory/yaml_spec.rb b/spec/unit/indirector/inventory/yaml_spec.rb
new file mode 100644
index 000000000..9f0c54353
--- /dev/null
+++ b/spec/unit/indirector/inventory/yaml_spec.rb
@@ -0,0 +1,221 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/node/inventory'
+require 'puppet/indirector/inventory/yaml'
+require 'puppet/indirector/request'
+
+describe Puppet::Node::Inventory::Yaml do
+ def assert_search_matches(matching, nonmatching, query)
+ request = Puppet::Indirector::Request.new(:inventory, :search, nil, query)
+
+ Dir.stubs(:glob).returns(matching.keys + nonmatching.keys)
+ [matching, nonmatching].each do |examples|
+ examples.each do |key, value|
+ YAML.stubs(:load_file).with(key).returns value
+ end
+ end
+ Puppet::Node::Inventory::Yaml.new.search(request).should =~ matching.values.map {|facts| facts.name}
+ end
+
+ it "should return node names that match the search query options" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '4'),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "i386", 'processor_count' => '4', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '4'),
+ "/path/to/nonmatching1.yaml" => Puppet::Node::Facts.new("nonmatchingnode1", "architecture" => "powerpc", 'processor_count' => '5'),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5'),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3", 'processor_count' => '4'),
+ },
+ {'facts.architecture' => 'i386', 'facts.processor_count' => '4'}
+ )
+ end
+
+ it "should return empty array when no nodes match the search query options" do
+ assert_search_matches({}, {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '10'),
+ "/path/to/nonmatching1.yaml" => Puppet::Node::Facts.new("nonmatchingnode1", "architecture" => "powerpc", 'processor_count' => '5'),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5'),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3", 'processor_count' => '4'),
+ },
+ {'facts.processor_count.lt' => '4', 'facts.processor_count.gt' => '4'}
+ )
+ end
+
+
+ it "should return node names that match the search query options with the greater than operator" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '10', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '4'),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '3'),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3" ),
+ },
+ {'facts.processor_count.gt' => '4'}
+ )
+ end
+
+ it "should return node names that match the search query options with the less than operator" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '30', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '50' ),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '100'),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3" ),
+ },
+ {'facts.processor_count.lt' => '50'}
+ )
+ end
+
+ it "should return node names that match the search query options with the less than or equal to operator" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '5'),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '50', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '100' ),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '5000'),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3" ),
+ },
+ {'facts.processor_count.le' => '50'}
+ )
+ end
+
+ it "should return node names that match the search query options with the greater than or equal to operator" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => "i386", 'processor_count' => '100'),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => "powerpc", 'processor_count' => '50', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "powerpc", 'processor_count' => '40'),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '9' ),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3" ),
+ },
+ {'facts.processor_count.ge' => '50'}
+ )
+ end
+
+ it "should return node names that match the search query options with the not equal operator" do
+ assert_search_matches({
+ '/path/to/matching.yaml' => Puppet::Node::Facts.new("matchingnode", "architecture" => 'arm' ),
+ '/path/to/matching1.yaml' => Puppet::Node::Facts.new("matchingnode1", "architecture" => 'powerpc', 'randomfact' => 'foo')
+ },
+ {
+ "/path/to/nonmatching.yaml" => Puppet::Node::Facts.new("nonmatchingnode", "architecture" => "i386" ),
+ "/path/to/nonmatching2.yaml" => Puppet::Node::Facts.new("nonmatchingnode2", "architecture" => "i386", 'processor_count' => '9' ),
+ "/path/to/nonmatching3.yaml" => Puppet::Node::Facts.new("nonmatchingnode3" ),
+ },
+ {'facts.architecture.ne' => 'i386'}
+ )
+ end
+
+ def apply_timestamp(facts, timestamp)
+ facts.timestamp = timestamp
+ facts
+ end
+
+ it "should be able to query based on meta.timestamp.gt" do
+ assert_search_matches({
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ },
+ {
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {'meta.timestamp.gt' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp.le" do
+ assert_search_matches({
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ },
+ {'meta.timestamp.le' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp.lt" do
+ assert_search_matches({
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ },
+ {
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {'meta.timestamp.lt' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp.ge" do
+ assert_search_matches({
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ },
+ {'meta.timestamp.ge' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp.eq" do
+ assert_search_matches({
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ },
+ {'meta.timestamp.eq' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp" do
+ assert_search_matches({
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ },
+ {'meta.timestamp' => '2010-10-15'}
+ )
+ end
+
+ it "should be able to query based on meta.timestamp.ne" do
+ assert_search_matches({
+ '/path/to/2010-11-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-01", {}), Time.parse("2010-11-01")),
+ '/path/to/2010-11-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-11-10", {}), Time.parse("2010-11-10")),
+ '/path/to/2010-10-01.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-01", {}), Time.parse("2010-10-01")),
+ '/path/to/2010-10-10.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-10", {}), Time.parse("2010-10-10")),
+ },
+ {
+ '/path/to/2010-10-15.yaml' => apply_timestamp(Puppet::Node::Facts.new("2010-10-15", {}), Time.parse("2010-10-15")),
+ },
+ {'meta.timestamp.ne' => '2010-10-15'}
+ )
+ end
+end
diff --git a/spec/unit/network/http/api/v1_spec.rb b/spec/unit/network/http/api/v1_spec.rb
index 23a291cf3..d47fc8d81 100644
--- a/spec/unit/network/http/api/v1_spec.rb
+++ b/spec/unit/network/http/api/v1_spec.rb
@@ -76,6 +76,18 @@ describe Puppet::Network::HTTP::API::V1 do
@tester.uri2indirection("GET", "/env/foos/bar", {}).method.should == :search
end
+ it "should choose 'find' as the indirection method if the http method is a GET and the indirection name is facts" do
+ @tester.uri2indirection("GET", "/env/facts/bar", {}).method.should == :find
+ end
+
+ it "should choose 'save' as the indirection method if the http method is a PUT and the indirection name is facts" do
+ @tester.uri2indirection("PUT", "/env/facts/bar", {}).method.should == :save
+ end
+
+ it "should choose 'search' as the indirection method if the http method is a GET and the indirection name is inventory" do
+ @tester.uri2indirection("GET", "/env/inventory/search", {}).method.should == :search
+ end
+
it "should choose 'delete' as the indirection method if the http method is a DELETE and the indirection name is singular" do
@tester.uri2indirection("DELETE", "/env/foo/bar", {}).method.should == :destroy
end
diff --git a/spec/unit/network/http/handler_spec.rb b/spec/unit/network/http/handler_spec.rb
index 8464ae68e..68c7b9aa3 100755
--- a/spec/unit/network/http/handler_spec.rb
+++ b/spec/unit/network/http/handler_spec.rb
@@ -344,17 +344,20 @@ describe Puppet::Network::HTTP::Handler do
@handler.do_search(@irequest, @request, @response)
end
- it "should return a 404 when searching returns an empty array" do
- @model_class.stubs(:name).returns "my name"
- @handler.expects(:set_response).with { |response, body, status| status == 404 }
+ it "should return [] when searching returns an empty array" do
+ @handler.expects(:accept_header).with(@request).returns "one,two"
@model_class.stubs(:search).returns([])
+ @model_class.expects(:render_multiple).with(@oneformat, []).returns "[]"
+
+
+ @handler.expects(:set_response).with { |response, data| data == "[]" }
@handler.do_search(@irequest, @request, @response)
end
it "should return a 404 when searching returns nil" do
@model_class.stubs(:name).returns "my name"
@handler.expects(:set_response).with { |response, body, status| status == 404 }
- @model_class.stubs(:search).returns([])
+ @model_class.stubs(:search).returns(nil)
@handler.do_search(@irequest, @request, @response)
end
end