diff options
-rwxr-xr-x | ext/puppet-test | 24 | ||||
-rw-r--r-- | lib/puppet/indirector/resource_type.rb | 5 | ||||
-rw-r--r-- | lib/puppet/indirector/resource_type/parser.rb | 27 | ||||
-rw-r--r-- | lib/puppet/indirector/resource_type/rest.rb | 7 | ||||
-rw-r--r-- | lib/puppet/resource/type.rb | 34 | ||||
-rwxr-xr-x | spec/unit/indirector/resource_type/parser.rb | 75 | ||||
-rwxr-xr-x | spec/unit/indirector/resource_type/rest.rb | 15 | ||||
-rwxr-xr-x | spec/unit/resource/type.rb | 41 |
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 |