#!/usr/bin/env ruby
$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/
require 'puppettest'
require 'puppettest/resourcetesting'
require 'puppettest/railstesting'
class TestResource < Test::Unit::TestCase
include PuppetTest
include PuppetTest::ParserTesting
include PuppetTest::ResourceTesting
include PuppetTest::RailsTesting
Parser = Puppet::Parser
AST = Parser::AST
def setup
super
Puppet[:trace] = false
@interp, @scope, @source = mkclassframing
end
def test_initialize
args = {:type => "resource", :title => "testing",
:source => @source, :scope => @scope}
# Check our arg requirements
args.each do |name, value|
try = args.dup
try.delete(name)
assert_raise(Puppet::DevError) do
Parser::Resource.new(try)
end
end
args[:params] = paramify @source, :one => "yay", :three => "rah"
res = nil
assert_nothing_raised do
res = Parser::Resource.new(args)
end
# Make sure it got the parameters correctly.
assert_equal("yay", res[:one])
assert_equal("rah", res[:three])
assert_equal({:one => "yay", :three => "rah"}, res.to_hash)
end
def test_override
res = mkresource
# Now verify we can't override with any random class
assert_raise(Puppet::ParseError) do
res.set paramify(@scope.findclass("other"), "one" => "boo").shift
end
# And that we can with a subclass
assert_nothing_raised do
res.set paramify(@scope.findclass("sub1"), "one" => "boo").shift
end
# And that a different subclass can override a different parameter
assert_nothing_raised do
res.set paramify(@scope.findclass("sub2"), "three" => "boo").shift
end
# But not the same one
assert_raise(Puppet::ParseError) do
res.set paramify(@scope.findclass("sub2"), "one" => "something").shift
end
end
def test_merge
# Start with the normal one
res = mkresource
# Now create a resource from a different scope
other = mkresource :source => other, :params => {"one" => "boo"}
# Make sure we can't merge it
assert_raise(Puppet::ParseError) do
res.merge(other)
end
# Make one from a subscope
other = mkresource :source => "sub1", :params => {"one" => "boo"}
# Make sure it merges
assert_nothing_raised do
res.merge(other)
end
assert_equal("boo", res["one"])
end
def test_paramcheck
# First make a builtin resource
res = nil
assert_nothing_raised do
res = Parser::Resource.new :type => "file", :title => tempfile(),
:source => @source, :scope => @scope
end
%w{path group source schedule subscribe}.each do |param|
assert_nothing_raised("Param %s was considered invalid" % param) do
res.paramcheck(param)
end
end
%w{this bad noness}.each do |param|
assert_raise(Puppet::ParseError, "%s was considered valid" % param) do
res.paramcheck(param)
end
end
# Now create a defined resource
assert_nothing_raised do
res = Parser::Resource.new :type => "resource", :title => "yay",
:source => @source, :scope => @scope
end
%w{one two three schedule subscribe}.each do |param|
assert_nothing_raised("Param %s was considered invalid" % param) do
res.paramcheck(param)
end
end
%w{this bad noness}.each do |param|
assert_raise(Puppet::ParseError, "%s was considered valid" % param) do
res.paramcheck(param)
end
end
end
def test_to_trans
# First try translating a builtin resource
res = Parser::Resource.new :type => "file", :title => "/tmp",
:source => @source, :scope => @scope,
:params => paramify(@source, :owner => "nobody", :mode => "644")
obj = nil
assert_nothing_raised do
obj = res.to_trans
end
assert_instance_of(Puppet::TransObject, obj)
assert_equal(obj.type, res.type)
assert_equal(obj.name, res.title)
# TransObjects use strings, resources use symbols
hash = obj.to_hash.inject({}) { |h,a| h[a[0].intern] = a[1]; h }
assert_equal(hash, res.to_hash)
end
def test_adddefaults
# Set some defaults at the top level
top = {:one => "fun", :two => "shoe"}
@scope.setdefaults("resource", paramify(@source, top))
# Make a resource at that level
res = Parser::Resource.new :type => "resource", :title => "yay",
:source => @source, :scope => @scope
# Add the defaults
assert_nothing_raised do
res.adddefaults
end
# And make sure we got them
top.each do |p, v|
assert_equal(v, res[p])
end
# Now got a bit lower
other = @scope.newscope
# And create a resource
lowerres = Parser::Resource.new :type => "resource", :title => "funtest",
:source => @source, :scope => other
assert_nothing_raised do
lowerres.adddefaults
end
# And check
top.each do |p, v|
assert_equal(v, lowerres[p])
end
# Now add some of our own defaults
lower = {:one => "shun", :three => "free"}
other.setdefaults("resource", paramify(@source, lower))
otherres = Parser::Resource.new :type => "resource", :title => "yaytest",
:source => @source, :scope => other
should = top.dup
# Make sure the lower defaults beat the higher ones.
lower.each do |p, v| should[p] = v end
otherres.adddefaults
should.each do |p,v|
assert_equal(v, otherres[p])
end
end
def test_evaluate
# Make a definition that we know will, um, do something
@interp.newdefine "evaltest",
:arguments => [%w{one}, ["two", stringobj("755")]],
:code => resourcedef("file", "/tmp",
"owner" => varref("one"), "mode" => varref("two"))
res = Parser::Resource.new :type => "evaltest", :title => "yay",
:source => @source, :scope => @scope,
:params => paramify(@source, :one => "nobody")
# Now try evaluating
ret = nil
assert_nothing_raised do
ret = res.evaluate
end
# Make sure we can find our object now
result = @scope.findresource("File[/tmp]")
# Now make sure we got the code we expected.
assert_instance_of(Puppet::Parser::Resource, result)
assert_equal("file", result.type)
assert_equal("/tmp", result.title)
assert_equal("nobody", result["owner"])
assert_equal("755", result["mode"])
# And that we cannot find the old resource
assert_nil(@scope.findresource("Evaltest[yay]"),
"Evaluated resource was not deleted")
end
def test_addoverrides
# First create an override for an object that doesn't yet exist
over1 = mkresource :source => "sub1", :params => {:one => "yay"}
assert_nothing_raised do
@scope.setoverride(over1)
end
assert(over1.override, "Override was not marked so")
# Now make the resource
res = mkresource :source => "base", :params => {:one => "rah",
:three => "foo"}
# And add it to our scope
@scope.setresource(res)
# And make sure over1 has not yet taken affect
assert_equal("foo", res[:three], "Lost value")
# Now add an immediately binding override
over2 = mkresource :source => "sub1", :params => {:three => "yay"}
assert_nothing_raised do
@scope.setoverride(over2)
end
# And make sure it worked
assert_equal("yay", res[:three], "Override 2 was ignored")
# Now add our late-binding override
assert_nothing_raised do
res.addoverrides
end
# And make sure they're still around
assert_equal("yay", res[:one], "Override 1 lost")
assert_equal("yay", res[:three], "Override 2 lost")
# And finally, make sure that there are no remaining overrides
assert_nothing_raised do
res.addoverrides
end
end
def test_proxymethods
res = Parser::Resource.new :type => "evaltest", :title => "yay",
:source => @source, :scope => @scope
assert_equal("evaltest", res.type)
assert_equal("yay", res.title)
assert_equal(false, res.builtin?)
end
def test_addmetaparams
mkevaltest @interp
res = Parser::Resource.new :type => "evaltest", :title => "yay",
:source => @source, :scope => @scope,
:params => paramify(@source, :tag => "yay")
assert_nil(res[:schedule], "Got schedule already")
assert_nothing_raised do
res.addmetaparams
end
@scope.setvar("schedule", "daily")
# This is so we can test that it won't override already-set metaparams
@scope.setvar("tag", "funtest")
assert_nothing_raised do
res.addmetaparams
end
assert_equal("daily", res[:schedule], "Did not get metaparam")
assert_equal("yay", res[:tag], "Overrode explicitly-set metaparam")
assert_nil(res[:noop], "Got invalid metaparam")
end
def test_reference_conversion
# First try it as a normal string
ref = Parser::Resource::Reference.new(:type => "file", :title => "/tmp/ref1")
# Now create an obj that uses it
res = mkresource :type => "file", :title => "/tmp/resource",
:params => {:require => ref}
trans = nil
assert_nothing_raised do
trans = res.to_trans
end
assert_instance_of(Array, trans["require"])
assert_equal(["file", "/tmp/ref1"], trans["require"])
# Now try it when using an array of references.
two = Parser::Resource::Reference.new(:type => "file", :title => "/tmp/ref2")
res = mkresource :type => "file", :title => "/tmp/resource2",
:params => {:require => [ref, two]}
trans = nil
assert_nothing_raised do
trans = res.to_trans
end
assert_instance_of(Array, trans["require"][0])
trans["require"].each do |val|
assert_instance_of(Array, val)
assert_equal("file", val[0])
assert(val[1] =~ /\/tmp\/ref[0-9]/,
"Was %s instead of the file name" % val[1])
end
end
# This is a bit of a weird one -- the user should not actually know
# that components exist, so we want references to act like they're not
# builtin
def test_components_are_not_builtin
ref = Parser::Resource::Reference.new(:type => "component", :title => "yay")
assert_nil(ref.builtintype, "Component was considered builtin")
end
if Puppet.features.rails?
# Compare a parser resource to a rails resource.
def compare_resources(host, res, updating, options = {})
# to_rails now expects to be passed a resource, else it will create a new one
newobj = host.resources.find_by_restype_and_title(res.type, res.title)
assert_nothing_raised do
newobj = res.to_rails(host, newobj)
end
assert_instance_of(Puppet::Rails::Resource, newobj)
newobj.save
if updating
tail = "on update"
else
tail = ""
end
# Make sure we find our object and only our object
count = 0
obj = nil
Puppet::Rails::Resource.find(:all).each do |obj|
assert_equal(newobj.id, obj.id, "Found object has a different id than generated object %s" % tail)
count += 1
[:title, :restype, :line, :exported].each do |param|
if param == :restype
method = :type
else
method = param
end
assert_equal(res.send(method), obj[param],
"attribute %s was not set correctly in rails %s" % [param, tail])
end
end
assert_equal(1, count, "Got too many resources %s" % tail)
# Now make sure we can find it again
assert_nothing_raised do
obj = Puppet::Rails::Resource.find_by_restype_and_title(
res.type, res.title, :include => :param_names
)
end
assert_instance_of(Puppet::Rails::Resource, obj)
# Make sure we get the parameters back
params = options[:params] || [obj.param_names.collect { |p| p.name },
res.to_hash.keys].flatten.collect { |n| n.to_s }.uniq
params.each do |name|
param = obj.param_names.find_by_name(name)
if res[name]
assert(param, "resource did not keep %s %s" % [name, tail])
else
assert(! param, "resource did not delete %s %s" % [name, tail])
end
if param
values = param.param_values.collect { |pv| pv.value }
should = res[param.name]
should = [should] unless should.is_a?(Array)
assert_equal(should, values,
"%s was different %s" % [param.name, tail])
end
end
end
def test_to_rails
railsteardown
railsinit
res = mkresource :type => "file", :title => "/tmp/testing",
:source => @source, :scope => @scope,
:params => {:owner => "root", :source => ["/tmp/A", "/tmp/B"],
:mode => "755"}
res.line = 50
# We also need a Rails Host to store under
host = Puppet::Rails::Host.new(:name => Facter.hostname)
compare_resources(host, res, false, :params => %w{owner source mode})
# Now make some changes to our resource. We're removing the mode,
# changing the source, and adding 'check'.
res = mkresource :type => "file", :title => "/tmp/testing",
:source => @source, :scope => @scope,
:params => {:owner => "bin", :source => ["/tmp/A", "/tmp/C"],
:check => "checksum"}
res.line = 75
res.exported = true
compare_resources(host, res, true, :params => %w{owner source mode check})
end
end
# #472. Really, this still isn't the best behaviour, but at least
# it's consistent with what we have elsewhere.
def test_defaults_from_parent_classes
# Make a parent class with some defaults in it
@interp.newclass("base",
:code => defaultobj("file", :owner => "root", :group => "root")
)
# Now a mid-level class with some different values
@interp.newclass("middle", :parent => "base",
:code => defaultobj("file", :owner => "bin", :mode => "755")
)
# Now a lower class with its own defaults plus a resource
@interp.newclass("bottom", :parent => "middle",
:code => AST::ASTArray.new(:children => [
defaultobj("file", :owner => "adm", :recurse => "true"),
resourcedef("file", "/tmp/yayness", {})
])
)
# Now evaluate the class.
assert_nothing_raised("Failed to evaluate class tree") do
@scope.evalclasses("bottom")
end
# Make sure our resource got created.
res = @scope.findresource("File[/tmp/yayness]")
assert_nothing_raised("Could not add defaults") do
res.adddefaults
end
assert(res, "could not find resource")
{:owner => "adm", :recurse => "true", :group => "root", :mode => "755"}.each do |param, value|
assert_equal(value, res[param], "%s => %s did not inherit correctly" %
[param, value])
end
end
# The second part of #539 - make sure resources pass the arguments
# correctly.
def test_title_with_definitions
define = @interp.newdefine "yayness",
:code => resourcedef("file", "/tmp",
"owner" => varref("name"), "mode" => varref("title"))
klass = @interp.findclass("", "")
should = {:name => :owner, :title => :mode}
[
{:name => "one", :title => "two"},
{:title => "three"},
].each do |hash|
scope = mkscope :interp => @interp
args = {:type => "yayness", :title => hash[:title],
:source => klass, :scope => scope}
if hash[:name]
args[:params] = {:name => hash[:name]}
else
args[:params] = {} # override the defaults
end
res = nil
assert_nothing_raised("Could not create res with %s" % hash.inspect) do
res = mkresource(args)
end
assert_nothing_raised("Could not eval res with %s" % hash.inspect) do
res.evaluate
end
made = scope.findresource("File[/tmp]")
assert(made, "Did not create resource with %s" % hash.inspect)
should.each do |orig, param|
assert_equal(hash[orig] || hash[:title], made[param],
"%s was not set correctly with %s" % [param, hash.inspect])
end
end
end
end
# $Id: resource.rb 2439 2007-04-30 19:21:59Z luke $
syntax highlighted by Code2HTML, v. 0.9.1