summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast/node.rb
blob: 97e8de06ea415453ef1570836059909a03bd7a8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
class Puppet::Parser::AST
    # The specific code associated with a host.  Nodes are annoyingly unlike
    # other objects.  That's just the way it is, at least for now.
    class Node < AST::HostClass
        @name = :node
        attr_accessor :type, :args, :code, :parentclass

        #def evaluate(scope, facts = {})
        def evaluate(hash)
            scope = hash[:scope]
            facts = hash[:facts] || {}
            #scope.info "name is %s, type is %s" % [self.name, self.type]
            # nodes are never instantiated like a normal object,
            # but we need the type to be the name users would use for
            # instantiation, otherwise tags don't work out
            scope = scope.newscope(
                :type => self.type,
                :keyword => @keyword
            )
            scope.context = self.object_id

            # Mark this scope as a nodescope, so that classes will be
            # singletons within it
            scope.isnodescope

            # Now set all of the facts inside this scope
            facts.each { |var, value|
                scope.setvar(var, value)
            }

            if tmp = self.evalparent(scope)
                # Again, override our scope with the parent scope, if
                # there is one.
                scope = tmp
            end

            #scope.tag(@name)

            # We never pass the facts to the parent class, because they've
            # already been defined at this top-level scope.
            #super(scope, facts, @name, @name)

            # And then evaluate our code.
            @code.safeevaluate(:scope => scope)

            return scope
        end

        # Evaluate our parent class.
        def evalparent(scope)
            if @parentclass
                # This is pretty messed up.  I don't know if this will
                # work in the long term, but we need to evaluate the node
                # in our own scope, even though our parent node has
                # a scope associated with it, because otherwise we 1) won't
                # get our facts defined, and 2) we won't actually get the
                # objects returned, based on how nodes work.

                # We also can't just evaluate the node itself, because
                # it would create a node scope within this scope,
                # and that would cause mass havoc.
                node = nil

                # The 'node' method just returns a hash of the node
                # code and name.  It's used here, and in 'evalnode'.
                unless hash = scope.node(@parentclass)
                    raise Puppet::ParseError,
                        "Could not find parent node %s" %
                        @parentclass
                end

                node = hash[:node]
                type = nil
                if type = node.type
                    scope.tag(node.type)
                end

                if name = node.name
                    scope.tag(node.name) unless name == type
                end

                begin
                    code = node.code
                    code.safeevaluate(:scope => scope)
                rescue Puppet::ParseError => except
                    except.line = self.line
                    except.file = self.file
                    raise except
                rescue => detail
                    error = Puppet::ParseError.new(detail)
                    error.line = self.line
                    error.file = self.file
                    raise error
                end

                if node.parentclass
                    node.evalparent(scope)
                end
            end
        end

        def initialize(hash)
            @parentclass = nil
            super

        end
    end
end