summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/resource.rb156
-rwxr-xr-xspec/unit/resource.rb194
-rwxr-xr-xtest/language/ast/resource_reference.rb77
3 files changed, 242 insertions, 185 deletions
diff --git a/lib/puppet/resource.rb b/lib/puppet/resource.rb
index 508e21e8d..f991f539d 100644
--- a/lib/puppet/resource.rb
+++ b/lib/puppet/resource.rb
@@ -13,8 +13,7 @@ class Puppet::Resource
extend Puppet::Util::Pson
include Enumerable
attr_accessor :file, :line, :catalog, :exported, :virtual, :validate_parameters, :strict
- attr_reader :title, :namespaces
- attr_writer :relative_type
+ attr_reader :namespaces
require 'puppet/indirector'
extend Puppet::Indirector
@@ -166,6 +165,8 @@ class Puppet::Resource
extract_parameters(params)
end
+ resolve_type_and_title()
+
tag(self.type)
tag(self.title) if valid_tag?(self.title)
@@ -185,23 +186,38 @@ class Puppet::Resource
end
def title=(value)
- if klass = resource_type and klass.respond_to?(:canonicalize_ref)
- value = klass.canonicalize_ref(value)
- end
- @title = value
+ @unresolved_title = value
+ @title = nil
end
- # Canonize the type so we know it's always consistent.
- def relative_type
- munge_type_name(@relative_type)
+ def old_title
+ if type == "Class" and value == ""
+ @title = :main
+ return
+ end
+
+ if klass = resource_type
+ p klass
+ if type == "Class"
+ value = munge_type_name(resource_type.name)
+ end
+
+ if klass.respond_to?(:canonicalize_ref)
+ value = klass.canonicalize_ref(value)
+ end
+ elsif type == "Class"
+ value = munge_type_name(value)
+ end
+
+ @title = value
end
def resource_type
- case relative_type.to_s.downcase
- when "class"; find_hostclass
- when "node"; find_node
+ case type
+ when "Class"; find_hostclass(title)
+ when "Node"; find_node(title)
else
- find_builtin_resource_type || find_defined_resource_type
+ find_resource_type(type)
end
end
@@ -306,18 +322,26 @@ class Puppet::Resource
self
end
- def type
- munge_type_name(if r = resource_type
- resource_type.name
- else
- relative_type
- end)
+ # We have to lazy-evaluate this.
+ def title=(value)
+ @title = nil
+ @unresolved_title = value
end
- # Only allow people to set the relative type,
- # so we force it to be looked up each time.
+ # We have to lazy-evaluate this.
def type=(value)
- @relative_type = value
+ @type = nil
+ @unresolved_type = value || "Class"
+ end
+
+ def title
+ resolve_type_and_title unless @title
+ @title
+ end
+
+ def type
+ resolve_type_and_title unless @type
+ @type
end
def valid_parameter?(name)
@@ -330,21 +354,25 @@ class Puppet::Resource
private
- def find_node
- known_resource_types.node(title)
+ def find_node(name)
+ known_resource_types.node(name)
end
- def find_hostclass
+ def find_hostclass(title)
name = title == :main ? "" : title
known_resource_types.find_hostclass(namespaces, name)
end
- def find_builtin_resource_type
- Puppet::Type.type(relative_type.to_s.downcase.to_sym)
+ def find_resource_type(type)
+ find_builtin_resource_type(type) || find_defined_resource_type(type)
+ end
+
+ def find_builtin_resource_type(type)
+ Puppet::Type.type(type.to_s.downcase.to_sym)
end
- def find_defined_resource_type
- known_resource_types.find_definition(namespaces, relative_type.to_s.downcase)
+ def find_defined_resource_type(type)
+ known_resource_types.find_definition(namespaces, type.to_s.downcase)
end
# Produce a canonical method name.
@@ -381,8 +409,6 @@ class Puppet::Resource
return bucket
end
- private
-
def extract_parameters(params)
params.each do |param, value|
validate_parameter(param) if strict?
@@ -399,12 +425,72 @@ class Puppet::Resource
end
def munge_type_name(value)
- return :main if value == ""
+ return :main if value == :main
+ return "Class" if value == "" or value.nil? or value.to_s.downcase == "component"
+
+ value.to_s.split("::").collect { |s| s.capitalize }.join("::")
+ end
+
+ # This is an annoyingly complicated method for resolving qualified
+ # types as necessary, and putting them in type or title attributes.
+ def resolve_type_and_title
+ if @unresolved_type
+ @type = resolve_type
+ @unresolved_type = nil
+ end
+ if @unresolved_title
+ @title = resolve_title
+ @unresolved_title = nil
+ end
+ end
+
+ def resolve_type
+ type = munge_type_name(@unresolved_type)
+
+ case type
+ when "Class", "Node";
+ return type
+ else
+ # Otherwise, some kind of builtin or defined resource type
+ return munge_type_name(if r = find_resource_type(type)
+ r.name
+ else
+ type
+ end)
+ end
+ end
+
+ # This method only works if resolve_type was called first
+ def resolve_title
+ case @type
+ when "Node"; return @unresolved_title
+ when "Class";
+ resolve_title_for_class(@unresolved_title)
+ else
+ resolve_title_for_resource(@unresolved_title)
+ end
+ end
+
+ def resolve_title_for_class(title)
+ if title == "" or title == :main
+ return :main
+ end
+
+ if klass = find_hostclass(title)
+ result = klass.name
+
+ if klass.respond_to?(:canonicalize_ref)
+ result = klass.canonicalize_ref(result)
+ end
+ end
+ return munge_type_name(result || title)
+ end
- if value.nil? or value.to_s.downcase == "component"
- "Class"
+ def resolve_title_for_resource(title)
+ if type = find_resource_type(@type) and type.respond_to?(:canonicalize_ref)
+ return type.canonicalize_ref(title)
else
- value.to_s.split("::").collect { |s| s.capitalize }.join("::")
+ return title
end
end
end
diff --git a/spec/unit/resource.rb b/spec/unit/resource.rb
index 5b82c2936..0eacd0b90 100755
--- a/spec/unit/resource.rb
+++ b/spec/unit/resource.rb
@@ -48,7 +48,7 @@ describe Puppet::Resource do
it "should set its type to 'Class' and its title to the passed title if the passed type is :component and the title has no square brackets in it" do
ref = Puppet::Resource.new(:component, "foo")
ref.type.should == "Class"
- ref.title.should == "foo"
+ ref.title.should == "Foo"
end
it "should interpret the title as a reference and assign appropriately if the type is :component and the title contains square brackets" do
@@ -60,7 +60,7 @@ describe Puppet::Resource do
it "should set the type to 'Class' if it is nil and the title contains no square brackets" do
ref = Puppet::Resource.new(nil, "yay")
ref.type.should == "Class"
- ref.title.should == "yay"
+ ref.title.should == "Yay"
end
it "should interpret the title as a reference and assign appropriately if the type is nil and the title contains square brackets" do
@@ -113,108 +113,159 @@ describe Puppet::Resource do
end
it "should support specifying namespaces" do
- Puppet::Resource.new("file", "/my/file", :namespaces => [:foo]).namespaces.should == [:foo]
+ Puppet::Resource.new("file", "/my/file", :namespaces => ["foo"]).namespaces.should == ["foo"]
end
it "should convert namespaces to an array if not specified as one" do
- Puppet::Resource.new("file", "/my/file", :namespaces => :foo).namespaces.should == [:foo]
+ Puppet::Resource.new("file", "/my/file", :namespaces => "foo").namespaces.should == ["foo"]
end
it "should default to a single amespace of an empty string" do
Puppet::Resource.new("file", "/my/file").namespaces.should == [""]
end
- it "should be able to look up its resource type when the type is a builtin resource" do
- Puppet::Resource.new("file", "/my/file").resource_type.should equal(Puppet::Type.type(:file))
- end
+ describe "and munging its type and title" do
+ describe "when modeling a builtin resource" do
+ it "should be able to find the resource type" do
+ Puppet::Resource.new("file", "/my/file").resource_type.should equal(Puppet::Type.type(:file))
+ end
- it "should be able to look up its resource type via its environment when the type is a defined resource type" do
- resource = Puppet::Resource.new("foobar", "/my/file")
- type = Puppet::Resource::Type.new(:definition, "foobar")
- resource.environment.known_resource_types.add type
+ it "should set its type to the capitalized type name" do
+ Puppet::Resource.new("file", "/my/file").type.should == "File"
+ end
+ end
- resource.resource_type.should equal(type)
- end
+ describe "when modeling a defined resource" do
+ describe "that exists" do
+ before do
+ @type = Puppet::Resource::Type.new(:definition, "foo::bar")
+ Puppet::Node::Environment.new.known_resource_types.add @type
+ end
- it "should be able to look up its resource type via its environment when the type is a node" do
- resource = Puppet::Resource.new("node", "foobar")
- node = Puppet::Resource::Type.new(:node, "foobar")
- resource.environment.known_resource_types.add node
+ it "should set its type to the capitalized type name" do
+ Puppet::Resource.new("foo::bar", "/my/file").type.should == "Foo::Bar"
+ end
- resource.resource_type.should equal(node)
- end
+ it "should be able to find the resource type" do
+ Puppet::Resource.new("foo::bar", "/my/file").resource_type.should equal(@type)
+ end
- it "should be able to look up its resource type via its environment when the type is a class" do
- resource = Puppet::Resource.new("class", "foobar")
- klass = Puppet::Resource::Type.new(:hostclass, "foobar")
- resource.environment.known_resource_types.add klass
+ it "should set its title to the provided title" do
+ Puppet::Resource.new("foo::bar", "/my/file").title.should == "/my/file"
+ end
- resource.resource_type.should equal(klass)
- end
+ describe "and the resource is unqualified and models a qualified resource type" do
+ it "should set its type to the fully qualified resource type" do
+ Puppet::Resource.new("bar", "/my/file", :namespaces => %w{foo}).type.should == "Foo::Bar"
+ end
- it "should use its namespaces when looking up defined resource types" do
- resource = Puppet::Resource.new("bar", "/my/file", :namespaces => ["foo"])
- type = Puppet::Resource::Type.new(:definition, "foo::bar")
- resource.environment.known_resource_types.add type
+ it "should be able to find the resource type" do
+ Puppet::Resource.new("bar", "/my/file", :namespaces => %w{foo}).resource_type.should equal(@type)
+ end
+ end
+ end
- resource.resource_type.should equal(type)
- end
+ describe "that does not exist" do
+ it "should set its resource type to the capitalized resource type name" do
+ Puppet::Resource.new("foo::bar", "/my/file").type.should == "Foo::Bar"
+ end
+ end
+ end
- it "should use its namespaces to set its type name when looking up defined resource types" do
- type = Puppet::Resource::Type.new(:definition, "foo::bar")
- Puppet::Node::Environment.new.known_resource_types.add type
- resource = Puppet::Resource.new("bar", "/my/file", :namespaces => ["foo"])
- resource.type.should == "Foo::Bar"
- end
+ describe "when modeling a node" do
+ # Life's easier with nodes, because they can't be qualified.
+ it "should set its type to 'Node' and its title to the provided title" do
+ node = Puppet::Resource.new("node", "foo")
+ node.type.should == "Node"
+ node.title.should == "foo"
+ end
+ end
- it "should look up its resource type when set manually" do
- type = Puppet::Resource::Type.new(:definition, "foo::bar")
- Puppet::Node::Environment.new.known_resource_types.add type
- resource = Puppet::Resource.new("foo", "/my/file", :namespaces => ["foo"])
- resource.type = "bar"
- resource.type.should == "Foo::Bar"
- end
+ describe "when modeling a class" do
+ it "should set its type to 'Class'" do
+ Puppet::Resource.new("class", "foo").type.should == "Class"
+ end
- it "should use its namespaces when looking up host classes" do
- resource = Puppet::Resource.new("class", "bar", :namespaces => ["foo"])
- type = Puppet::Resource::Type.new(:hostclass, "foo::bar")
- resource.environment.known_resource_types.add type
+ describe "that exists" do
+ before do
+ @type = Puppet::Resource::Type.new(:hostclass, "foo::bar")
+ Puppet::Node::Environment.new.known_resource_types.add @type
+ end
+
+ it "should set its title to the capitalized, fully qualified resource type" do
+ Puppet::Resource.new("class", "foo::bar").title.should == "Foo::Bar"
+ end
+
+ it "should be able to find the resource type" do
+ Puppet::Resource.new("class", "foo::bar").resource_type.should equal(@type)
+ end
+
+ describe "and the resource is unqualified and models a qualified class" do
+ it "should set its title to the fully qualified resource type" do
+ Puppet::Resource.new("class", "bar", :namespaces => %w{foo}).title.should == "Foo::Bar"
+ end
+
+ it "should be able to find the resource type" do
+ Puppet::Resource.new("class", "bar", :namespaces => %w{foo}).resource_type.should equal(@type)
+ end
+
+ it "should set its type to 'Class'" do
+ Puppet::Resource.new("class", "bar", :namespaces => %w{foo}).type.should == "Class"
+ end
+ end
+ end
- resource.resource_type.should equal(type)
- end
+ describe "that does not exist" do
+ it "should set its type to 'Class' and its title to the capitalized provided name" do
+ klass = Puppet::Resource.new("class", "foo::bar")
+ klass.type.should == "Class"
+ klass.title.should == "Foo::Bar"
+ end
+ end
- it "should consider a class whose name is an empty string to be the main class" do
- type = Puppet::Resource::Type.new(:hostclass, "")
- Puppet::Node::Environment.new.known_resource_types.add type
+ describe "and its name is set to the empty string" do
+ it "should set its title to :main" do
+ Puppet::Resource.new("class", "").title.should == :main
+ end
+
+ describe "and a class exists whose name is the empty string" do # this was a bit tough to track down
+ it "should set its title to :main" do
+ @type = Puppet::Resource::Type.new(:hostclass, "")
+ Puppet::Node::Environment.new.known_resource_types.add @type
+
+ Puppet::Resource.new("class", "").title.should == :main
+ end
+ end
+ end
- resource = Puppet::Resource.new("class", "").type.should == :main
+ describe "and its name is set to :main" do
+ it "should set its title to :main" do
+ Puppet::Resource.new("class", :main).title.should == :main
+ end
+
+ describe "and a class exists whose name is the empty string" do # this was a bit tough to track down
+ it "should set its title to :main" do
+ @type = Puppet::Resource::Type.new(:hostclass, "")
+ Puppet::Node::Environment.new.known_resource_types.add @type
+
+ Puppet::Resource.new("class", :main).title.should == :main
+ end
+ end
+ end
+ end
end
it "should return nil when looking up resource types that don't exist" do
Puppet::Resource.new("foobar", "bar").resource_type.should be_nil
end
- it "should fail when an invalid parameter is used and parameter validation is enabled" do
- type = Puppet::Resource::Type.new(:definition, "foobar")
- Puppet::Node::Environment.new.known_resource_types.add type
- resource = Puppet::Resource.new("foobar", "/my/file", :validate_parameters => true)
- lambda { resource[:yay] = true }.should raise_error(ArgumentError)
- end
-
- it "should not fail when an invalid parameter is used and parameter validation is disabled" do
+ it "should not fail when an invalid parameter is used and strict mode is disabled" do
type = Puppet::Resource::Type.new(:definition, "foobar")
Puppet::Node::Environment.new.known_resource_types.add type
resource = Puppet::Resource.new("foobar", "/my/file")
resource[:yay] = true
end
- it "should not fail when a valid parameter is used and parameter validation is enabled" do
- type = Puppet::Resource::Type.new(:definition, "foobar", :arguments => {"yay" => nil})
- Puppet::Node::Environment.new.known_resource_types.add type
- resource = Puppet::Resource.new("foobar", "/my/file", :validate_parameters => true)
- resource[:yay] = true
- end
-
it "should be considered equivalent to another resource if their type and title match and no parameters are set" do
Puppet::Resource.new("file", "/f").should == Puppet::Resource.new("file", "/f")
end
@@ -239,10 +290,7 @@ describe Puppet::Resource do
Puppet::Resource.new("file", "/foo").should_not == Puppet::Resource.new("file", "/f")
end
- describe "when refering to a resource with name canonicalization" do
- before do
- end
-
+ describe "when referring to a resource with name canonicalization" do
it "should canonicalize its own name" do
res = Puppet::Resource.new("file", "/path/")
res.title.should == "/path"
diff --git a/test/language/ast/resource_reference.rb b/test/language/ast/resource_reference.rb
deleted file mode 100755
index 5abb0d6e5..000000000
--- a/test/language/ast/resource_reference.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env ruby
-#
-# Created by Luke A. Kanies on 2007-07-8.
-# Copyright (c) 2007. All rights reserved.
-
-require File.dirname(__FILE__) + '/../../lib/puppettest'
-
-require 'puppettest'
-require 'puppettest/parsertesting'
-
-class TestASTResourceReference < Test::Unit::TestCase
- include PuppetTest
- include PuppetTest::ParserTesting
- AST = Puppet::Parser::AST
-
- def newref(type, title)
- AST::ResourceReference.new(:type => type, :title => AST::String.new(:value => title))
- end
-
- def setup
- super
- @scope = mkscope
- @parser = Puppet::Parser::Parser.new(Puppet::Node::Environment.new)
- end
-
- # Related to #706, make sure resource references correctly translate to qualified types.
- def test_scoped_references
- @parser.newdefine "one"
- @parser.newdefine "one::two"
- @parser.newdefine "three"
- twoscope = @scope.newscope(:namespace => "one")
- assert(twoscope.find_definition("two"), "Could not find 'two' definition")
- title = "title"
-
- # First try a qualified type
- assert_equal("One::Two", newref("two", title).evaluate(twoscope).type,
- "Defined type was not made fully qualified")
-
- # Then try a type that does not need to be qualified
- assert_equal("One", newref("one", title).evaluate(twoscope).type,
- "Unqualified defined type was not handled correctly")
-
- # Then an unqualified type from within the one namespace
- assert_equal("Three", newref("three", title).evaluate(twoscope).type,
- "Defined type was not made fully qualified")
-
- # Then a builtin type
- assert_equal("File", newref("file", title).evaluate(twoscope).type,
- "Builtin type was not handled correctly")
-
- # Now try a type that does not exist, which should throw an error.
- assert_raise(Puppet::ParseError, "Did not fail on a missing type in a resource reference") do
- newref("nosuchtype", title).evaluate(twoscope)
- end
-
- # Now run the same tests, but with the classes
- @parser.newclass "four"
- @parser.newclass "one::five"
-
- # First try an unqualified type
- assert_equal("four", newref("class", "four").evaluate(twoscope).title,
- "Unqualified class was not found")
-
- # Then a qualified class
- assert_equal("one::five", newref("class", "five").evaluate(twoscope).title,
- "Class was not made fully qualified")
-
- # Then try a type that does not need to be qualified
- assert_equal("four", newref("class", "four").evaluate(twoscope).title,
- "Unqualified class was not handled correctly")
-
- # Now try a type that does not exist, which should throw an error.
- assert_raise(Puppet::ParseError, "Did not fail on a missing type in a resource reference") do
- newref("class", "nosuchclass").evaluate(twoscope)
- end
- end
-end