summaryrefslogtreecommitdiffstats
path: root/lib/puppet/parser/interpreter.rb
blob: f27c1c5c8120870f7ef73176a913fc7fd99e76ea (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
require 'puppet'
require 'timeout'
require 'puppet/rails'
require 'puppet/util/methodhelper'
require 'puppet/parser/parser'
require 'puppet/parser/compiler'
require 'puppet/parser/scope'

# The interpreter is a very simple entry-point class that
# manages the existence of the parser (e.g., replacing it
# when files are reparsed).  You can feed it a node and
# get the node's catalog back.
class Puppet::Parser::Interpreter
    include Puppet::Util

    attr_accessor :usenodes

    include Puppet::Util::Errors

    # Determine the configuration version for a given node's environment.
    def configuration_version(node)
        parser(node.environment).version
    end

    # evaluate our whole tree
    def compile(node)
        raise Puppet::ParseError, "Could not parse configuration; cannot compile on node %s" % node.name unless env_parser = parser(node.environment)
        begin
          return Puppet::Parser::Compiler.new(node, env_parser).compile
        rescue => detail
          puts detail.backtrace if Puppet[:trace]
          raise Puppet::Error, detail.to_s + " on node %s" % node.name
        end
    end

    # create our interpreter
    def initialize
        # The class won't always be defined during testing.
        if Puppet[:storeconfigs] 
            if Puppet.features.rails?
                Puppet::Rails.init
            else
                raise Puppet::Error, "Rails is missing; cannot store configurations"
            end
        end

        @parsers = {}
    end

    # Return the parser for a specific environment.
    def parser(environment)
        if ! @parsers[environment] or @parsers[environment].reparse?
            # This will throw an exception if it does not succeed.  We only
            # want to get rid of the old parser if we successfully create a new
            # one.
            begin
                tmp = create_parser(environment)
                @parsers[environment].clear if @parsers[environment]
                @parsers[environment] = tmp
            rescue => detail
                # If a parser already exists, than assume that we logged the
                # exception elsewhere and reuse the parser.  If one doesn't
                # exist, then reraise.
                if @parsers[environment]
                    Puppet.err detail
                else
                    raise detail
                end
            end
        end
        @parsers[environment]
    end

    private

    # Create a new parser object and pre-parse the configuration.
    def create_parser(environment)
        begin
            parser = Puppet::Parser::Parser.new(:environment => environment)
            if code = Puppet.settings.value(:code, environment) and code != ""
                parser.string = code
            else
                file = Puppet.settings.value(:manifest, environment)
                parser.file = file
            end
            parser.parse
            return parser
        rescue => detail
            msg = "Could not parse"
            if environment and environment != ""
                msg += " for environment %s" % environment
            end
            msg += ": %s" % detail.to_s
            error = Puppet::Error.new(msg)
            error.set_backtrace(detail.backtrace)
            raise error
        end
    end
end