Class: Puppet::Parser::Compiler

Inherits:
Object
  • Object
show all
Includes:
Resource::TypeCollectionHelper, Util, Util::Errors
Defined in:
lib/puppet/parser/compiler.rb

Overview

Maintain a graph of scopes, along with a bunch of data about the individual catalog we’re compiling.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Resource::TypeCollectionHelper

#known_resource_types

Methods included from Util::Errors

#adderrorcontext, #devfail, #error_context, #exceptwrap, #fail

Methods included from Util

activerecord_version, benchmark, chuser, classproxy, #execfail, #execpipe, execute, logmethods, memory, proxy, recmkdir, secure_open, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, which, withumask

Methods included from Util::POSIX

#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid

Constructor Details

#initialize(node, options = {}) ⇒ Compiler

Returns a new instance of Compiler.



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/puppet/parser/compiler.rb', line 182

def initialize(node, options = {})
  @node = node

  options.each do |param, value|
    begin
      send(param.to_s + "=", value)
    rescue NoMethodError
      raise ArgumentError, "Compiler objects do not accept #{param}"
    end
  end

  initvars
end

Instance Attribute Details

#catalogObject (readonly)

Returns the value of attribute catalog.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def catalog
  @catalog
end

#collectionsObject (readonly)

Returns the value of attribute collections.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def collections
  @collections
end

#factsObject (readonly)

Returns the value of attribute facts.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def facts
  @facts
end

#nodeObject (readonly)

Returns the value of attribute node.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def node
  @node
end

#node_scopeObject (readonly)

Returns the value of attribute node_scope.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def node_scope
  @node_scope
end

#relationshipsObject (readonly)

Returns the value of attribute relationships.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def relationships
  @relationships
end

#resourcesObject (readonly)

Returns the value of attribute resources.



33
34
35
# File 'lib/puppet/parser/compiler.rb', line 33

def resources
  @resources
end

Class Method Details

.compile(node) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/puppet/parser/compiler.rb', line 17

def self.compile(node)
   # We get these from the environment and only cache them in a thread
   # variable for the duration of the compilation.  If nothing else is using
   # the thread, though, we can leave 'em hanging round with no ill effects,
   # and this is safer than cleaning them at the end and assuming that will
   # stick until the next entry to this function.
   Thread.current[:known_resource_types] = nil
   Thread.current[:env_module_directories] = nil

   # ...and we actually do the compile now we have caching ready.
   new(node).compile.to_resource
 rescue => detail
   puts detail.backtrace if Puppet[:trace]
   raise Puppet::Error, "#{detail} on node #{node.name}"
end

Instance Method Details

#add_class(name) ⇒ Object

Store the fact that we’ve evaluated a class



85
86
87
# File 'lib/puppet/parser/compiler.rb', line 85

def add_class(name)
  @catalog.add_class(name) unless name == ""
end

#add_collection(coll) ⇒ Object

Add a collection to the global list.



36
37
38
# File 'lib/puppet/parser/compiler.rb', line 36

def add_collection(coll)
  @collections << coll
end

#add_override(override) ⇒ Object

Store a resource override.



45
46
47
48
49
50
51
52
53
54
# File 'lib/puppet/parser/compiler.rb', line 45

def add_override(override)
  # If possible, merge the override in immediately.
  if resource = @catalog.resource(override.ref)
    resource.merge(override)
  else
    # Otherwise, store the override for later; these
    # get evaluated in Resource#finish.
    @resource_overrides[override.ref] << override
  end
end

#add_relationship(dep) ⇒ Object



40
41
42
# File 'lib/puppet/parser/compiler.rb', line 40

def add_relationship(dep)
  @relationships << dep
end

#add_resource(scope, resource) ⇒ Object

Store a resource in our resource table.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/puppet/parser/compiler.rb', line 57

def add_resource(scope, resource)
  @resources << resource

  # Note that this will fail if the resource is not unique.
  @catalog.add_resource(resource)

  if resource.type.to_s.downcase != "class" && resource[:stage]
    raise ArgumentError, "Only classes can set 'stage'; normal resources like #{resource} cannot change run stage"
  end

  # Stages should not be inside of classes.  They are always a
  # top-level container, regardless of where they appear in the
  # manifest.
  return if resource.type.to_s.downcase == "stage"

  # This adds a resource to the class it lexically appears in in the
  # manifest.
  if resource.type.to_s.downcase != "class"
    return @catalog.add_edge(scope.resource, resource)
  end
end

#ast_nodes?Boolean

Do we use nodes found in the code, vs. the external node sources?

Returns:

  • (Boolean)


80
81
82
# File 'lib/puppet/parser/compiler.rb', line 80

def ast_nodes?
  known_resource_types.nodes?
end

#classlistObject

Return a list of all of the defined classes.



91
92
93
# File 'lib/puppet/parser/compiler.rb', line 91

def classlist
  @catalog.classes
end

#compileObject

Compiler our catalog. This mostly revolves around finding and evaluating classes. This is the main entry into our catalog.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/puppet/parser/compiler.rb', line 97

def compile
  # Set the client's parameters into the top scope.
  set_node_parameters
  create_settings_scope

  evaluate_main

  evaluate_ast_node

  evaluate_node_classes

  evaluate_generators

  finish

  fail_on_unevaluated

  @catalog
end

#delete_collection(coll) ⇒ Object

LAK:FIXME There are no tests for this.



118
119
120
# File 'lib/puppet/parser/compiler.rb', line 118

def delete_collection(coll)
  @collections.delete(coll) if @collections.include?(coll)
end

#environmentObject

Return the node’s environment.



123
124
125
126
127
128
129
# File 'lib/puppet/parser/compiler.rb', line 123

def environment
  unless defined?(@environment)
    @environment = (node.environment and node.environment != "") ? node.environment : nil
  end
  Puppet::Node::Environment.current = @environment
  @environment
end

#evaluate_classes(classes, scope, lazy_evaluate = true) ⇒ Object

Evaluate each specified class in turn. If there are any classes we can’t find, just tag the catalog and move on. This method really just creates resource objects that point back to the classes, and then the resources are themselves evaluated later in the process.

Raises:



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/puppet/parser/compiler.rb', line 140

def evaluate_classes(classes, scope, lazy_evaluate = true)
  raise Puppet::DevError, "No source for scope passed to evaluate_classes" unless scope.source
  found = []
  param_classes = nil
  # if we are a param class, save the classes hash
  # and transform classes to be the keys
  if classes.class == Hash
    param_classes = classes
    classes = classes.keys
  end
  classes.each do |name|
    # If we can find the class, then make a resource that will evaluate it.
    if klass = scope.find_hostclass(name)

      if param_classes
        resource = klass.ensure_in_catalog(scope, param_classes[name] || {})
      else
        found << name and next if scope.class_scope(klass)
        resource = klass.ensure_in_catalog(scope)
      end

      # If they've disabled lazy evaluation (which the :include function does),
      # then evaluate our resource immediately.
      resource.evaluate unless lazy_evaluate
      found << name
    else
      Puppet.warning "Could not find class #{name} for #{node.name}"
      @catalog.tag(name)
    end
  end
  found
end

#evaluate_node_classesObject

Evaluate all of the classes specified by the node.



132
133
134
# File 'lib/puppet/parser/compiler.rb', line 132

def evaluate_node_classes
  evaluate_classes(@node.classes, topscope)
end

#evaluate_relationshipsObject



173
174
175
# File 'lib/puppet/parser/compiler.rb', line 173

def evaluate_relationships
  @relationships.each { |rel| rel.evaluate(catalog) }
end

#findresource(*args) ⇒ Object

Return a resource by either its ref or its type and title.



178
179
180
# File 'lib/puppet/parser/compiler.rb', line 178

def findresource(*args)
  @catalog.resource(*args)
end

#newscope(parent, options = {}) ⇒ Object

Create a new scope, with either a specified parent scope or using the top scope.



198
199
200
201
202
203
204
# File 'lib/puppet/parser/compiler.rb', line 198

def newscope(parent, options = {})
  parent ||= topscope
  options[:compiler] = self
  scope = Puppet::Parser::Scope.new(options)
  scope.parent = parent
  scope
end

#resource_overrides(resource) ⇒ Object

Return any overrides for the given resource.



207
208
209
# File 'lib/puppet/parser/compiler.rb', line 207

def resource_overrides(resource)
  @resource_overrides[resource.ref]
end

#topscopeObject

The top scope is usually the top-level scope, but if we’re using AST nodes, then it is instead the node’s scope.



213
214
215
# File 'lib/puppet/parser/compiler.rb', line 213

def topscope
  node_scope || @topscope
end