summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xext/puppet-test24
-rw-r--r--lib/puppet/indirector/resource_type.rb5
-rw-r--r--lib/puppet/indirector/resource_type/parser.rb27
-rw-r--r--lib/puppet/indirector/resource_type/rest.rb7
-rw-r--r--lib/puppet/resource/type.rb34
-rwxr-xr-xspec/unit/indirector/resource_type/parser.rb75
-rwxr-xr-xspec/unit/indirector/resource_type/rest.rb15
-rwxr-xr-xspec/unit/resource/type.rb41
8 files changed, 228 insertions, 0 deletions
diff --git a/ext/puppet-test b/ext/puppet-test
index 53333076f..61397e74b 100755
--- a/ext/puppet-test
+++ b/ext/puppet-test
@@ -229,6 +229,30 @@ Suite.new :local_catalog, "Local catalog handling" do
end
end
+Suite.new :resource_type, "Managing resource types" do
+ newtest :find, "Find a type" do
+ Puppet::Resource::Type.terminus_class = :parser
+ ARGV.each do |name|
+ json = Puppet::Resource::Type.find(name).to_pson
+ data = PSON.parse(json)
+ p Puppet::Resource::Type.from_pson(data)
+ end
+ end
+
+ newtest :search_types, "Find all types" do
+ Puppet::Resource::Type.terminus_class = :rest
+ result = Puppet::Resource::Type.search("*")
+ result.each { |r| p r }
+ end
+
+ newtest :restful_type, "Find a type and return it via REST" do
+ Puppet::Resource::Type.terminus_class = :rest
+ ARGV.each do |name|
+ p Puppet::Resource::Type.find(name)
+ end
+ end
+end
+
Suite.new :remote_catalog, "Remote catalog handling" do
def prepare
$args[:cache] = false
diff --git a/lib/puppet/indirector/resource_type.rb b/lib/puppet/indirector/resource_type.rb
new file mode 100644
index 000000000..0564dc2b3
--- /dev/null
+++ b/lib/puppet/indirector/resource_type.rb
@@ -0,0 +1,5 @@
+require 'puppet/resource/type'
+
+# A stub class, so our constants work.
+class Puppet::Indirector::ResourceType # :nodoc:
+end
diff --git a/lib/puppet/indirector/resource_type/parser.rb b/lib/puppet/indirector/resource_type/parser.rb
new file mode 100644
index 000000000..81ec1bf76
--- /dev/null
+++ b/lib/puppet/indirector/resource_type/parser.rb
@@ -0,0 +1,27 @@
+require 'puppet/resource/type'
+require 'puppet/indirector/code'
+require 'puppet/indirector/resource_type'
+
+class Puppet::Indirector::ResourceType::Parser < Puppet::Indirector::Code
+ desc "Return the data-form of a resource type."
+
+ def find(request)
+ krt = request.environment.known_resource_types
+
+ # This is a bit ugly.
+ [:hostclass, :definition, :node].each do |type|
+ if r = krt.send(type, request.key)
+ return r
+ end
+ end
+ nil
+ end
+
+ def search(request)
+ raise ArgumentError, "Only '*' is acceptable as a search request" unless request.key == "*"
+ krt = request.environment.known_resource_types
+ result = [krt.hostclasses.values, krt.definitions.values, krt.nodes.values].flatten
+ return nil if result.empty?
+ result
+ end
+end
diff --git a/lib/puppet/indirector/resource_type/rest.rb b/lib/puppet/indirector/resource_type/rest.rb
new file mode 100644
index 000000000..66d332011
--- /dev/null
+++ b/lib/puppet/indirector/resource_type/rest.rb
@@ -0,0 +1,7 @@
+require 'puppet/resource/type'
+require 'puppet/indirector/rest'
+require 'puppet/indirector/resource_type'
+
+class Puppet::Indirector::ResourceType::Rest < Puppet::Indirector::REST
+ desc "Retrieve resource types via a REST HTTP interface."
+end
diff --git a/lib/puppet/resource/type.rb b/lib/puppet/resource/type.rb
index 402df06a8..3657f89b5 100644
--- a/lib/puppet/resource/type.rb
+++ b/lib/puppet/resource/type.rb
@@ -6,6 +6,7 @@ require 'puppet/parser/ast/leaf'
require 'puppet/dsl'
class Puppet::Resource::Type
+ Puppet::ResourceType = self
include Puppet::Util::InlineDocs
include Puppet::Util::Warnings
include Puppet::Util::Errors
@@ -19,6 +20,38 @@ class Puppet::Resource::Type
define_method("#{t}?") { self.type == t }
end
+ require 'puppet/indirector'
+ extend Puppet::Indirector
+ indirects :resource_type, :terminus_class => :parser
+
+ def self.from_pson(data)
+ name = data.delete('name') or raise ArgumentError, "Resource Type names must be specified"
+ type = data.delete('type') || "definition"
+
+ data = data.inject({}) { |result, ary| result[ary[0].intern] = ary[1]; result }
+
+ new(type, name, data)
+ end
+
+ def to_pson_data_hash
+ data = [:code, :doc, :line, :file, :parent].inject({}) do |hash, param|
+ next hash unless value = self.send(param)
+ hash[param.to_s] = value
+ hash
+ end
+
+ data['arguments'] = arguments.dup
+
+ data['name'] = name
+ data['type'] = type
+
+ data
+ end
+
+ def to_pson(*args)
+ to_pson_data_hash.to_pson(*args)
+ end
+
# Are we a child of the passed class? Do a recursive search up our
# parentage tree to figure it out.
def child_of?(klass)
@@ -260,3 +293,4 @@ class Puppet::Resource::Type
end
end
end
+
diff --git a/spec/unit/indirector/resource_type/parser.rb b/spec/unit/indirector/resource_type/parser.rb
new file mode 100755
index 000000000..331ca1c9b
--- /dev/null
+++ b/spec/unit/indirector/resource_type/parser.rb
@@ -0,0 +1,75 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/resource_type/parser'
+
+describe Puppet::Indirector::ResourceType::Parser do
+ before do
+ @terminus = Puppet::Indirector::ResourceType::Parser.new
+ @request = Puppet::Indirector::Request.new(:resource_type, :find, "foo")
+ @krt = Puppet::Resource::TypeCollection.new(@request.environment)
+ @request.environment.stubs(:known_resource_types).returns @krt
+ end
+
+ it "should be registered with the resource_type indirection" do
+ Puppet::Indirector::Terminus.terminus_class(:resource_type, :parser).should equal(Puppet::Indirector::ResourceType::Parser)
+ end
+
+ describe "when finding" do
+ it "should use the request's environment's list of known resource types" do
+ @request.environment.known_resource_types.expects(:hostclass).returns nil
+
+ @terminus.find(@request)
+ end
+
+ it "should return any found type" do
+ type = @krt.add(Puppet::Resource::Type.new(:hostclass, "foo"))
+
+ @terminus.find(@request).should == type
+ end
+
+ it "should return nil if no type can be found" do
+ @terminus.find(@request).should be_nil
+ end
+
+ it "should prefer definitions to nodes" do
+ type = @krt.add(Puppet::Resource::Type.new(:hostclass, "foo"))
+ node = @krt.add(Puppet::Resource::Type.new(:node, "foo"))
+
+ @terminus.find(@request).should == type
+ end
+ end
+
+ describe "when searching" do
+ before do
+ @request.key = "*"
+ end
+
+ it "should use the request's environment's list of known resource types" do
+ @request.environment.known_resource_types.expects(:hostclasses).returns({})
+
+ @terminus.search(@request)
+ end
+
+ it "should fail if anyther other than '*' was provided as the search key" do
+ @request.key = "foo*"
+ lambda { @terminus.search(@request) }.should raise_error(ArgumentError)
+ end
+
+ it "should return all known types" do
+ type = @krt.add(Puppet::Resource::Type.new(:hostclass, "foo"))
+ node = @krt.add(Puppet::Resource::Type.new(:node, "bar"))
+ define = @krt.add(Puppet::Resource::Type.new(:definition, "baz"))
+
+ result = @terminus.search(@request)
+ result.should be_include(type)
+ result.should be_include(node)
+ result.should be_include(define)
+ end
+
+ it "should return nil if no types can be found" do
+ @terminus.search(@request).should be_nil
+ end
+ end
+end
diff --git a/spec/unit/indirector/resource_type/rest.rb b/spec/unit/indirector/resource_type/rest.rb
new file mode 100755
index 000000000..28196d53a
--- /dev/null
+++ b/spec/unit/indirector/resource_type/rest.rb
@@ -0,0 +1,15 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+require 'puppet/indirector/resource_type/rest'
+
+describe Puppet::Indirector::ResourceType::Rest do
+ it "should be registered with the resource_type indirection" do
+ Puppet::Indirector::Terminus.terminus_class(:resource_type, :rest).should equal(Puppet::Indirector::ResourceType::Rest)
+ end
+
+ it "should be a subclass of Puppet::Indirector::Rest" do
+ Puppet::Indirector::ResourceType::Rest.superclass.should == Puppet::Indirector::REST
+ end
+end
diff --git a/spec/unit/resource/type.rb b/spec/unit/resource/type.rb
index bbf2f736d..8c024d7e4 100755
--- a/spec/unit/resource/type.rb
+++ b/spec/unit/resource/type.rb
@@ -23,6 +23,47 @@ describe Puppet::Resource::Type do
end
end
+ it "should indirect 'resource_type'" do
+ Puppet::Resource::Type.indirection.name.should == :resource_type
+ end
+
+ it "should default to 'parser' for its terminus class" do
+ Puppet::Resource::Type.indirection.terminus_class.should == :parser
+ end
+
+ describe "when converting to json" do
+ before do
+ @type = Puppet::Resource::Type.new(:hostclass, "foo")
+ end
+
+ def from_json(json)
+ Puppet::Resource::Type.from_pson(json)
+ end
+
+ def double_convert
+ Puppet::Resource::Type.from_pson(PSON.parse(@type.to_pson))
+ end
+
+ it "should include the name and type" do
+ double_convert.name.should == @type.name
+ double_convert.type.should == @type.type
+ end
+
+ it "should include any arguments" do
+ @type.set_arguments("one" => nil, "two" => "foo")
+
+ double_convert.arguments.should == {"one" => nil, "two" => "foo"}
+ end
+
+ it "should include any extra attributes" do
+ @type.file = "/my/file"
+ @type.line = 50
+
+ double_convert.file.should == "/my/file"
+ double_convert.line.should == 50
+ end
+ end
+
describe "when a node" do
it "should allow a regex as its name" do
lambda { Puppet::Resource::Type.new(:node, /foo/) }.should_not raise_error