Class: Puppet::Pops::Loader::PuppetPlanInstantiator
- Defined in:
- lib/puppet/pops/loader/puppet_plan_instantiator.rb
Overview
source that when called evaluates the Puppet logic it contains.
Class Method Summary collapse
-
.create(loader, typed_name, source_ref, pp_code_string) ⇒ Functions::Function
Produces an instance of the Function class with the given typed_name, or fails with an error if the given puppet source does not produce this instance when evaluated.
-
.create_from_model(plan_definition, loader) ⇒ Array<TypedName, Functions.Function>
Creates Function class and instantiates it based on a FunctionDefinition model.
- .create_function_class(plan_definition) ⇒ Object
Class Method Details
.create(loader, typed_name, source_ref, pp_code_string) ⇒ Functions::Function
Produces an instance of the Function class with the given typed_name, or fails with an error if the given puppet source does not produce this instance when evaluated.
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 |
# File 'lib/puppet/pops/loader/puppet_plan_instantiator.rb', line 19 def self.create(loader, typed_name, source_ref, pp_code_string) parser = Parser::EvaluatingParser.new() # parse and validate result = parser.parse_string(pp_code_string, source_ref) # The parser attaches all definitions, including those nested in apply # blocks, to the Program object. Node definitions in apply blocks are # perfectly legal and don't count as the file containing multiple # definitions for this purpose. By this point, we've already validated that # there are no node definitions *outside* apply blocks, so we simply ignore # them here. definitions = result.definitions.reject { |definition| definition.is_a?(Puppet::Pops::Model::NodeDefinition) } # Only one plan is allowed (and no other definitions) case definitions.size when 0 raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - it is empty.") % { source_ref: source_ref, plan_name: typed_name.name } when 1 # ok else raise ArgumentError, _("The code loaded from %{source_ref} must contain only the plan '%{plan_name}' - it has additional definitions.") % { source_ref: source_ref, plan_name: typed_name.name } end the_plan_definition = definitions[0] unless the_plan_definition.is_a?(Model::PlanDefinition) raise ArgumentError, _("The code loaded from %{source_ref} does not define the plan '%{plan_name}' - no plan found.") % { source_ref: source_ref, plan_name: typed_name.name } end unless the_plan_definition.name == typed_name.name expected = typed_name.name actual = the_plan_definition.name raise ArgumentError, _("The code loaded from %{source_ref} produced plan with the wrong name, expected %{expected}, actual %{actual}") % { source_ref: source_ref, expected: expected, actual: actual } end unless result.body == the_plan_definition raise ArgumentError, _("The code loaded from %{source} contains additional logic - can only contain the plan %{plan_name}") % { source: source_ref, plan_name: typed_name.name } end # Adapt the function definition with loader - this is used from logic contained in it body to find the # loader to use when making calls to the new function API. Such logic have a hard time finding the closure (where # the loader is known - hence this mechanism private_loader = loader.private_loader Adapters::LoaderAdapter.adapt(the_plan_definition).loader_name = private_loader.loader_name # Cannot bind loaded functions to global scope, that must be done without binding that scope as # loaders survive a compilation. closure_scope = nil created = create_function_class(the_plan_definition) # create the function instance - it needs closure (scope), and loader (i.e. where it should start searching for things # when calling functions etc. # It should be bound to global scope created.new(closure_scope, private_loader) end |
.create_from_model(plan_definition, loader) ⇒ Array<TypedName, Functions.Function>
Creates Function class and instantiates it based on a FunctionDefinition model
79 80 81 82 83 |
# File 'lib/puppet/pops/loader/puppet_plan_instantiator.rb', line 79 def self.create_from_model(plan_definition, loader) created = create_function_class(plan_definition) typed_name = TypedName.new(:plan, plan_definition.name) [typed_name, created.new(nil, loader)] end |
.create_function_class(plan_definition) ⇒ Object
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/puppet/pops/loader/puppet_plan_instantiator.rb', line 85 def self.create_function_class(plan_definition) # Create a 4x function wrapper around a named closure Puppet::Functions.create_function(plan_definition.name, Puppet::Functions::PuppetFunction) do # TODO: should not create a new evaluator per function init_dispatch(Evaluator::Closure::Named.new( plan_definition.name, Evaluator::EvaluatorImpl.new(), plan_definition )) end end |