If you create a fact that does not have a value for some class of hosts, then there is no variable available to the template at all (rather than the variable existing and returning 'nil'), so if you test for that fact in a template and a node that doesn't have a value for that fact runs, an exception is raised (because method_missing cannot find a variable).
The only way to test for an empty/nil fact value is by using @scope.lookupvar("variable"), false) which is a bit of black magic and that is not a good way to go about because that relies on the implementation details of the Template Wrapper? class.
The exception being raised is probably there to catch common cases, like people screwing up a fact value in a template.
Holoway looked at things on IRC and he thinks that the Puppet::Parser::Template Wrapper? class is doing the right thing, it just needs the equivilant of either has_fact? or exists? As a possible patch, he suggested the following:
diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb
index 13823d4..47857c4 100644
--- a/lib/puppet/parser/templatewrapper.rb
+++ b/lib/puppet/parser/templatewrapper.rb
@@ -19,6 +19,14 @@ class Puppet::Parser::TemplateWrapper
@scope.parser.watch_file(@file)
end
end
+
+ def has_fact?(fact)
+ if @scope.lookupvar(name.to_s, false) == :undefined
+ false
+ else
+ true
+ end
+ end
# Ruby treats variables like methods, so we can cheat here and
# trap missing vars like they were missing methods.