summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/ast/node.rb
blob: e4e69bed9531efebffc9ead8eb7f95eb524a9953 (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
109
110
111
112
113
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)
            origscope = hash[:scope]
            facts = hash[:facts] || {}

            # 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

            pscope = origscope
            #pscope = if ! Puppet[:lexical] or hash[:asparent]
            #    @scope
            #else
            #    origscope
            #end

            scope = pscope.newscope(
                :type => self.type,
                :keyword => @keyword
            )
            scope.context = self.object_id

            # 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)

            # Mark our node name as a class, too, but strip it of the domain
            # name.  Make the mark before we evaluate the code, so that it is
            # marked within the code itself.
            scope.setclass(self.object_id, @type.sub(/\..+/, ''))

            # 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

                begin
                    code = node.code
                    code.safeevaluate(:scope => scope, :asparent => true)
                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