class Puppet::Parser::AST::PopsBridge::Program

Bridges the top level “Program” produced by the pops parser. Its main purpose is to give one point where all definitions are instantiated (actually defined since the Puppet 3x terminology is somewhat misleading - the definitions are instantiated, but instances of the created types are not created, that happens when classes are included / required, nodes are matched and when resources are instantiated by a resource expression (which is also used to instantiate a host class).

Attributes

context[R]
program_model[R]

Public Class Methods

new(program_model, context = {}) click to toggle source
   # File lib/puppet/parser/ast/pops_bridge.rb
77 def initialize(program_model, context = {})
78   @program_model = program_model
79   @context = context
80   @ast_transformer ||= Puppet::Pops::Model::AstTransformer.new(@context[:file])
81 end

Public Instance Methods

each() { |self| ... } click to toggle source

Adapts to 3x where top level constructs needs to have each to iterate over children. Short circuit this by yielding self. This means that the HostClass container will call this bridge instance with `instantiate`.

    # File lib/puppet/parser/ast/pops_bridge.rb
115 def each
116   yield self
117 end
evaluate(scope) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
108 def evaluate(scope)
109   Puppet::Pops::Parser::EvaluatingParser.singleton.evaluate(scope, program_model)
110 end
instantiate(modname) click to toggle source

This is the 3x API, the 3x AST searches through all code to find the instructions that can be instantiated. This Pops-model based instantiation relies on the parser to build this list while parsing (which is more efficient as it avoids one full scan of all logic via recursive enumeration/yield)

    # File lib/puppet/parser/ast/pops_bridge.rb
 87 def instantiate(modname)
 88 
 89   @program_model.definitions.map do |d|
 90     case d
 91     when Puppet::Pops::Model::HostClassDefinition
 92       instantiate_HostClassDefinition(d, modname)
 93     when Puppet::Pops::Model::ResourceTypeDefinition
 94       instantiate_ResourceTypeDefinition(d, modname)
 95     when Puppet::Pops::Model::NodeDefinition
 96       instantiate_NodeDefinition(d, modname)
 97     else
 98       loaders = Puppet::Pops::Loaders.loaders
 99       loaders.instantiate_definition(d, loaders.find_loader(modname))
100 
101       # The 3x logic calling this will not know what to do with the result, it is compacted away at the end
102       nil
103     end
104   end.flatten().compact() # flatten since node definition may have returned an array
105                           # Compact since 4x definitions are not understood by compiler
106 end
is_definitions_only?() click to toggle source

Returns true if this Program only contains definitions

    # File lib/puppet/parser/ast/pops_bridge.rb
120 def is_definitions_only?
121   is_definition?(program_model)
122 end

Private Instance Methods

absolute_reference(ref) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
237 def absolute_reference(ref)
238   if ref.nil? || ref.empty? || ref.start_with?('::')
239     ref
240   else
241     "::#{ref}"
242   end
243 end
args_from_definition(o, modname, expr_class = Expression) click to toggle source

Produces a hash with data for Definition and HostClass

    # File lib/puppet/parser/ast/pops_bridge.rb
187 def args_from_definition(o, modname, expr_class = Expression)
188   args = {
189    :arguments => o.parameters.collect {|p| instantiate_Parameter(p) },
190    :argument_types => create_type_map(o),
191    :module_name => modname
192   }
193   unless is_nop?(o.body)
194     args[:code] = expr_class.new(:value => o.body)
195   end
196   @ast_transformer.merge_location(args, o)
197 end
code() click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
229 def code()
230   Expression.new(:value => @value)
231 end
create_type_map(definition) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
148 def create_type_map(definition)
149   result = {}
150   # No need to do anything if there are no parameters
151   return result unless definition.parameters.size > 0
152 
153   # No need to do anything if there are no typed parameters
154   typed_parameters = definition.parameters.select {|p| p.type_expr }
155   return result if typed_parameters.empty?
156 
157   # If there are typed parameters, they need to be evaluated to produce the corresponding type
158   # instances. This evaluation requires a scope. A scope is not available when doing deserialization
159   # (there is also no initialized evaluator). When running apply and test however, the environment is
160   # reused and we may reenter without a scope (which is fine). A debug message is then output in case
161   # there is the need to track down the odd corner case. See {#obtain_scope}.
162   #
163   scope = obtain_scope
164   if scope
165     evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
166     typed_parameters.each do |p|
167       result[p.name] = evaluator.evaluate(scope, p.type_expr)
168     end
169   end
170   result
171 end
instantiate_HostClassDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
199 def instantiate_HostClassDefinition(o, modname)
200   args = args_from_definition(o, modname, ExpressionSupportingReturn)
201   args[:parent] = absolute_reference(o.parent_class)
202   Puppet::Resource::Type.new(:hostclass, o.name, @context.merge(args))
203 end
instantiate_NodeDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
211 def instantiate_NodeDefinition(o, modname)
212   args = { :module_name => modname }
213 
214   unless is_nop?(o.body)
215     args[:code] = Expression.new(:value => o.body)
216   end
217 
218   unless is_nop?(o.parent)
219     args[:parent] = @ast_transformer.hostname(o.parent)
220   end
221   args = @ast_transformer.merge_location(args, o)
222 
223   host_matches = @ast_transformer.hostname(o.host_matches)
224   host_matches.collect do |name|
225     Puppet::Resource::Type.new(:node, name, @context.merge(args))
226   end
227 end
instantiate_Parameter(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
139 def instantiate_Parameter(o)
140   # 3x needs parameters as an array of `[name]` or `[name, value_expr]`
141   if o.value
142     [o.name, Expression.new(:value => o.value)]
143   else
144     [o.name]
145   end
146 end
instantiate_ResourceTypeDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
205 def instantiate_ResourceTypeDefinition(o, modname)
206   instance = Puppet::Resource::Type.new(:definition, o.name, @context.merge(args_from_definition(o, modname, ExpressionSupportingReturn)))
207   Puppet::Pops::Loaders.register_runtime3_type(instance.name, o.locator.to_uri(o))
208   instance
209 end
is_definition?(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
126 def is_definition?(o)
127   case o
128   when Puppet::Pops::Model::Program
129     is_definition?(o.body)
130   when Puppet::Pops::Model::BlockExpression
131     o.statements.all {|s| is_definition?(s) }
132   when Puppet::Pops::Model::Definition
133     true
134   else
135     false
136   end
137 end
is_nop?(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
233 def is_nop?(o)
234   @ast_transformer.is_nop?(o)
235 end
obtain_scope() click to toggle source

Obtains the scope or issues a warning if :global_scope is not bound

    # File lib/puppet/parser/ast/pops_bridge.rb
174 def obtain_scope
175   scope = Puppet.lookup(:global_scope) do
176     # This occurs when testing and when applying a catalog (there is no scope available then), and
177     # when running tests that run a partial setup.
178     # This is bad if the logic is trying to compile, but a warning can not be issues since it is a normal
179     # use case that there is no scope when requesting the type in order to just get the parameters.
180     Puppet.debug {_("Instantiating Resource with type checked parameters - scope is missing, skipping type checking.")}
181     nil
182   end
183   scope
184 end