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
78 def initialize(program_model, context = {})
79   @program_model = program_model
80   @context = context
81   @ast_transformer ||= Puppet::Pops::Model::AstTransformer.new(@context[:file])
82 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
116 def each
117   yield self
118 end
evaluate(scope) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
109 def evaluate(scope)
110   Puppet::Pops::Parser::EvaluatingParser.singleton.evaluate(scope, program_model)
111 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
 88 def instantiate(modname)
 89 
 90   @program_model.definitions.map do |d|
 91     case d
 92     when Puppet::Pops::Model::HostClassDefinition
 93       instantiate_HostClassDefinition(d, modname)
 94     when Puppet::Pops::Model::ResourceTypeDefinition
 95       instantiate_ResourceTypeDefinition(d, modname)
 96     when Puppet::Pops::Model::NodeDefinition
 97       instantiate_NodeDefinition(d, modname)
 98     else
 99       loaders = Puppet::Pops::Loaders.loaders
100       loaders.instantiate_definition(d, loaders.find_loader(modname))
101 
102       # The 3x logic calling this will not know what to do with the result, it is compacted away at the end
103       nil
104     end
105   end.flatten().compact() # flatten since node definition may have returned an array
106                           # Compact since 4x definitions are not understood by compiler
107 end
is_definitions_only?() click to toggle source

Returns true if this Program only contains definitions

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

Private Instance Methods

absolute_reference(ref) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
238 def absolute_reference(ref)
239   if ref.nil? || ref.empty? || ref.start_with?('::')
240     ref
241   else
242     "::#{ref}"
243   end
244 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
188 def args_from_definition(o, modname, expr_class = Expression)
189   args = {
190    :arguments => o.parameters.collect {|p| instantiate_Parameter(p) },
191    :argument_types => create_type_map(o),
192    :module_name => modname
193   }
194   unless is_nop?(o.body)
195     args[:code] = expr_class.new(:value => o.body)
196   end
197   @ast_transformer.merge_location(args, o)
198 end
code() click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
230 def code()
231   Expression.new(:value => @value)
232 end
create_type_map(definition) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
149 def create_type_map(definition)
150   result = {}
151   # No need to do anything if there are no parameters
152   return result unless definition.parameters.size > 0
153 
154   # No need to do anything if there are no typed parameters
155   typed_parameters = definition.parameters.select {|p| p.type_expr }
156   return result if typed_parameters.empty?
157 
158   # If there are typed parameters, they need to be evaluated to produce the corresponding type
159   # instances. This evaluation requires a scope. A scope is not available when doing deserialization
160   # (there is also no initialized evaluator). When running apply and test however, the environment is
161   # reused and we may reenter without a scope (which is fine). A debug message is then output in case
162   # there is the need to track down the odd corner case. See {#obtain_scope}.
163   #
164   scope = obtain_scope
165   if scope
166     evaluator = Puppet::Pops::Parser::EvaluatingParser.singleton
167     typed_parameters.each do |p|
168       result[p.name] = evaluator.evaluate(scope, p.type_expr)
169     end
170   end
171   result
172 end
instantiate_HostClassDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
200 def instantiate_HostClassDefinition(o, modname)
201   args = args_from_definition(o, modname, ExpressionSupportingReturn)
202   args[:parent] = absolute_reference(o.parent_class)
203   Puppet::Resource::Type.new(:hostclass, o.name, @context.merge(args))
204 end
instantiate_NodeDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
212 def instantiate_NodeDefinition(o, modname)
213   args = { :module_name => modname }
214 
215   unless is_nop?(o.body)
216     args[:code] = Expression.new(:value => o.body)
217   end
218 
219   unless is_nop?(o.parent)
220     args[:parent] = @ast_transformer.hostname(o.parent)
221   end
222   args = @ast_transformer.merge_location(args, o)
223 
224   host_matches = @ast_transformer.hostname(o.host_matches)
225   host_matches.collect do |name|
226     Puppet::Resource::Type.new(:node, name, @context.merge(args))
227   end
228 end
instantiate_Parameter(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
140 def instantiate_Parameter(o)
141   # 3x needs parameters as an array of `[name]` or `[name, value_expr]`
142   if o.value
143     [o.name, Expression.new(:value => o.value)]
144   else
145     [o.name]
146   end
147 end
instantiate_ResourceTypeDefinition(o, modname) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
206 def instantiate_ResourceTypeDefinition(o, modname)
207   instance = Puppet::Resource::Type.new(:definition, o.name, @context.merge(args_from_definition(o, modname, ExpressionSupportingReturn)))
208   Puppet::Pops::Loaders.register_runtime3_type(instance.name, o.locator.to_uri(o))
209   instance
210 end
is_definition?(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
127 def is_definition?(o)
128   case o
129   when Puppet::Pops::Model::Program
130     is_definition?(o.body)
131   when Puppet::Pops::Model::BlockExpression
132     o.statements.all {|s| is_definition?(s) }
133   when Puppet::Pops::Model::Definition
134     true
135   else
136     false
137   end
138 end
is_nop?(o) click to toggle source
    # File lib/puppet/parser/ast/pops_bridge.rb
234 def is_nop?(o)
235   @ast_transformer.is_nop?(o)
236 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
175 def obtain_scope
176   scope = Puppet.lookup(:global_scope) do
177     # This occurs when testing and when applying a catalog (there is no scope available then), and
178     # when running tests that run a partial setup.
179     # This is bad if the logic is trying to compile, but a warning can not be issues since it is a normal
180     # use case that there is no scope when requesting the type in order to just get the parameters.
181     Puppet.debug {_("Instantiating Resource with type checked parameters - scope is missing, skipping type checking.")}
182     nil
183   end
184   scope
185 end