1
require 'puppet/parser/ast/branch'
3
require 'puppet/util/warnings'
5
# The AST class for defined types, which is also the base class
7
class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch
8
include Puppet::Util::Warnings
16
attr_accessor :classname, :arguments, :code, :scope, :keyword
17
attr_accessor :exported, :namespace, :parser, :virtual, :name
19
attr_reader :parentclass
25
# Create a resource that knows how to evaluate our actual code.
27
resource = Puppet::Parser::Resource.new(:type => self.class.name, :title => self.classname, :scope => scope, :source => scope.source)
29
scope.catalog.tag(*resource.tags)
31
scope.compiler.add_resource(scope, resource)
36
# Now evaluate the code associated with this class or definition.
37
def evaluate_code(resource)
39
scope = subscope(resource.scope, resource)
41
set_resource_parameters(scope, resource)
44
return self.code.safeevaluate(scope)
50
def initialize(hash = {})
55
# Convert the arguments to a hash for ease of later use.
57
unless @arguments.is_a? Array
58
@arguments = [@arguments]
62
oldargs.each do |arg, val|
69
# Deal with metaparams in the argument list.
70
@arguments.each do |arg, defvalue|
71
next unless Puppet::Type.metaparamclass(arg)
73
warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg
75
raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname]
81
@parser.findclass(namespace, parentclass)
84
# Set our parent class, with a little check to avoid some potential
86
def parentclass=(name)
87
if name == self.classname
88
parsefail "Parent classes must have dissimilar names"
94
# Hunt down our class object.
96
return nil unless @parentclass
98
# Cache our result, since it should never change.
99
unless defined?(@parentobj)
100
unless tmp = find_parentclass
101
parsefail "Could not find %s parent %s" % [self.class.name, @parentclass]
105
parsefail "Parent classes must have dissimilar names"
113
# Create a new subscope in which to evaluate our code.
114
def subscope(scope, resource)
116
:resource => resource,
117
:keyword => self.keyword,
118
:namespace => self.namespace,
123
scope = scope.newscope(args)
133
# Check whether a given argument is valid. Searches up through
134
# any parent classes that might exist.
135
def validattr?(param)
138
if @arguments.include?(param)
139
# It's a valid arg for us
141
elsif param == "name"
143
# elsif defined? @parentclass and @parentclass
144
# # Else, check any existing parent
145
# if parent = @scope.lookuptype(@parentclass) and parent != []
146
# return parent.validarg?(param)
147
# elsif builtin = Puppet::Type.type(@parentclass)
148
# return builtin.validattr?(param)
150
# raise Puppet::Error, "Could not find parent class %s" %
153
elsif Puppet::Type.metaparam?(param)
156
# Or just return false
163
# Set any arguments passed by the resource as variables in the scope.
164
def set_resource_parameters(scope, resource)
165
args = symbolize_options(resource.to_hash || {})
167
# Verify that all required arguments are either present or
168
# have been provided with defaults.
170
self.arguments.each { |arg, default|
172
unless args.include?(arg)
173
if defined? default and ! default.nil?
174
default = default.safeevaluate scope
176
#Puppet.debug "Got default %s for %s in %s" %
177
# [default.inspect, arg.inspect, @name.inspect]
179
parsefail "Must pass %s to %s of type %s" %
180
[arg, resource.title, @classname]
186
# Set each of the provided arguments as variables in the
187
# definition's scope.
188
args.each { |arg,value|
189
unless validattr?(arg)
190
parsefail "%s does not accept attribute %s" % [@classname, arg]
194
scope.setvar(arg.to_s, args[arg])
198
scope.setvar("title", resource.title) unless args.include? :title
199
scope.setvar("name", resource.name) unless args.include? :name