~ubuntu-branches/ubuntu/oneiric/puppet/oneiric-security

« back to all changes in this revision

Viewing changes to lib/puppet/parser/ast/definition.rb

  • Committer: Bazaar Package Importer
  • Author(s): Micah Anderson
  • Date: 2008-07-26 15:43:45 UTC
  • mto: (3.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20080726154345-1fmgo76b4l72ulvc
ImportĀ upstreamĀ versionĀ 0.24.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
require 'puppet/parser/ast/branch'
 
2
 
 
3
require 'puppet/util/warnings'
 
4
 
 
5
# The AST class for defined types, which is also the base class
 
6
# nodes and classes.
 
7
class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch
 
8
    include Puppet::Util::Warnings
 
9
    class << self
 
10
        attr_accessor :name
 
11
    end
 
12
 
 
13
    # The class name
 
14
    @name = :definition
 
15
 
 
16
    attr_accessor :classname, :arguments, :code, :scope, :keyword
 
17
    attr_accessor :exported, :namespace, :parser, :virtual, :name
 
18
 
 
19
    attr_reader :parentclass
 
20
 
 
21
    def child_of?(klass)
 
22
        false
 
23
    end
 
24
 
 
25
    # Create a resource that knows how to evaluate our actual code.
 
26
    def evaluate(scope)
 
27
        resource = Puppet::Parser::Resource.new(:type => self.class.name, :title => self.classname, :scope => scope, :source => scope.source)
 
28
 
 
29
        scope.catalog.tag(*resource.tags)
 
30
 
 
31
        scope.compiler.add_resource(scope, resource)
 
32
 
 
33
        return resource
 
34
    end
 
35
 
 
36
    # Now evaluate the code associated with this class or definition.
 
37
    def evaluate_code(resource)
 
38
        # Create a new scope.
 
39
        scope = subscope(resource.scope, resource)
 
40
 
 
41
        set_resource_parameters(scope, resource)
 
42
 
 
43
        if self.code
 
44
            return self.code.safeevaluate(scope)
 
45
        else
 
46
            return nil
 
47
        end
 
48
    end
 
49
 
 
50
    def initialize(hash = {})
 
51
        @arguments = nil
 
52
        @parentclass = nil
 
53
        super
 
54
 
 
55
        # Convert the arguments to a hash for ease of later use.
 
56
        if @arguments
 
57
            unless @arguments.is_a? Array
 
58
                @arguments = [@arguments]
 
59
            end
 
60
            oldargs = @arguments
 
61
            @arguments = {}
 
62
            oldargs.each do |arg, val|
 
63
                @arguments[arg] = val
 
64
            end
 
65
        else
 
66
            @arguments = {}
 
67
        end
 
68
 
 
69
        # Deal with metaparams in the argument list.
 
70
        @arguments.each do |arg, defvalue|
 
71
            next unless Puppet::Type.metaparamclass(arg)
 
72
            if defvalue
 
73
                warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg
 
74
            else
 
75
                raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname]
 
76
            end
 
77
        end
 
78
    end
 
79
 
 
80
    def find_parentclass
 
81
        @parser.findclass(namespace, parentclass)
 
82
    end
 
83
 
 
84
    # Set our parent class, with a little check to avoid some potential
 
85
    # weirdness.
 
86
    def parentclass=(name)
 
87
        if name == self.classname
 
88
            parsefail "Parent classes must have dissimilar names"
 
89
        end
 
90
 
 
91
        @parentclass = name
 
92
    end
 
93
 
 
94
    # Hunt down our class object.
 
95
    def parentobj
 
96
        return nil unless @parentclass
 
97
 
 
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]
 
102
            end
 
103
 
 
104
            if tmp == self
 
105
                parsefail "Parent classes must have dissimilar names"
 
106
            end
 
107
 
 
108
            @parentobj = tmp
 
109
        end
 
110
        @parentobj
 
111
    end
 
112
 
 
113
    # Create a new subscope in which to evaluate our code.
 
114
    def subscope(scope, resource)
 
115
        args = {
 
116
            :resource => resource,
 
117
            :keyword => self.keyword,
 
118
            :namespace => self.namespace,
 
119
            :source => self
 
120
        }
 
121
 
 
122
        oldscope = scope
 
123
        scope = scope.newscope(args)
 
124
        scope.source = self
 
125
 
 
126
        return scope
 
127
    end
 
128
 
 
129
    def to_s
 
130
        classname
 
131
    end
 
132
 
 
133
    # Check whether a given argument is valid.  Searches up through
 
134
    # any parent classes that might exist.
 
135
    def validattr?(param)
 
136
        param = param.to_s
 
137
 
 
138
        if @arguments.include?(param)
 
139
            # It's a valid arg for us
 
140
            return true
 
141
        elsif param == "name"
 
142
            return true
 
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)
 
149
#                else
 
150
#                    raise Puppet::Error, "Could not find parent class %s" %
 
151
#                        @parentclass
 
152
#                end
 
153
        elsif Puppet::Type.metaparam?(param)
 
154
            return true
 
155
        else
 
156
            # Or just return false
 
157
            return false
 
158
        end
 
159
    end
 
160
 
 
161
    private
 
162
 
 
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 || {})
 
166
 
 
167
        # Verify that all required arguments are either present or
 
168
        # have been provided with defaults.
 
169
        if self.arguments
 
170
            self.arguments.each { |arg, default|
 
171
                arg = arg.to_sym
 
172
                unless args.include?(arg)
 
173
                    if defined? default and ! default.nil?
 
174
                        default = default.safeevaluate scope
 
175
                        args[arg] = default
 
176
                        #Puppet.debug "Got default %s for %s in %s" %
 
177
                        #    [default.inspect, arg.inspect, @name.inspect]
 
178
                    else
 
179
                        parsefail "Must pass %s to %s of type %s" %
 
180
                                [arg, resource.title, @classname]
 
181
                    end
 
182
                end
 
183
            }
 
184
        end
 
185
 
 
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]
 
191
            end
 
192
 
 
193
            exceptwrap do
 
194
                scope.setvar(arg.to_s, args[arg])
 
195
            end
 
196
        }
 
197
 
 
198
        scope.setvar("title", resource.title) unless args.include? :title
 
199
        scope.setvar("name", resource.name) unless args.include? :name
 
200
    end
 
201
end