class Puppet::Pops::Loader::PuppetResourceTypeImplInstantiator
The PuppetResourceTypeImplInstantiator instantiates a Puppet::Pops::ResourceTypeImpl object. given a Puppet Programming language source that when called evaluates the Puppet logic it contains.
Public Class Methods
create(loader, typed_name, source_ref, pp_code_string)
click to toggle source
Produces an instance of Puppet::Pops::ResourceTypeImpl, or fails with an error if the given puppet source does not produce such an instance when evaluated.
@param loader [Loader] The loader the function is associated with @param typed_name [TypedName] the type / name of the resource type impl to load @param source_ref [URI, String] a reference to the source / origin of the puppet code to evaluate @param pp_code_string [String] puppet code in a string
@return [Puppet::Pops::ResourceTypeImpl] - an instantiated ResourceTypeImpl
# File lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb 18 def self.create(loader, typed_name, source_ref, pp_code_string) 19 parser = Parser::EvaluatingParser.new() 20 21 # parse and validate 22 model = parser.parse_string(pp_code_string, source_ref) 23 statements = if model.is_a?(Model::Program) 24 if model.body.is_a?(Model::BlockExpression) 25 model.body.statements 26 else 27 [model.body] 28 end 29 else 30 EMPTY_ARRAY 31 end 32 statements = statements.reject { |s| s.is_a?(Model::Nop) } 33 if statements.empty? 34 raise ArgumentError, _("The code loaded from %{source_ref} does not create the resource type '%{type_name}' - it is empty") % { source_ref: source_ref, type_name: typed_name.name } 35 end 36 37 rname = Resource::ResourceTypeImpl._pcore_type.name 38 unless statements.find do |s| 39 if s.is_a?(Model::CallMethodExpression) 40 functor_expr = s.functor_expr 41 functor_expr.is_a?(Model::NamedAccessExpression) && 42 functor_expr.left_expr.is_a?(Model::QualifiedReference) && 43 functor_expr.left_expr.cased_value == rname && 44 functor_expr.right_expr.is_a?(Model::QualifiedName) && 45 functor_expr.right_expr.value == 'new' 46 else 47 false 48 end 49 end 50 raise ArgumentError, _("The code loaded from %{source_ref} does not create the resource type '%{type_name}' - no call to %{rname}.new found.") % { source_ref: source_ref, type_name: typed_name.name, rname: rname } 51 end 52 53 unless statements.size == 1 54 raise ArgumentError, _("The code loaded from %{source_ref} must contain only the creation of resource type '%{type_name}' - it has additional logic.") % { source_ref: source_ref, type_name: typed_name.name } 55 end 56 57 closure_scope = Puppet.lookup(:global_scope) { {} } 58 resource_type_impl = parser.evaluate(closure_scope, model) 59 60 unless resource_type_impl.is_a?(Puppet::Pops::Resource::ResourceTypeImpl) 61 got = resource_type.class 62 raise ArgumentError, _("The code loaded from %{source_ref} does not define the resource type '%{type_name}' - got '%{got}'.") % { source_ref: source_ref, type_name: typed_name.name, got: got } 63 end 64 65 unless resource_type_impl.name == typed_name.name 66 expected = typed_name.name 67 actual = resource_type_impl.name 68 raise ArgumentError, _("The code loaded from %{source_ref} produced resource type with the wrong name, expected '%{expected}', actual '%{actual}'") % { source_ref: source_ref, expected: expected, actual: actual } 69 end 70 71 # Adapt the resource type definition with loader - this is used from logic contained in it body to find the 72 # loader to use when making calls to the new function API. Such logic have a hard time finding the closure (where 73 # the loader is known - hence this mechanism 74 Adapters::LoaderAdapter.adapt(resource_type_impl).loader_name = loader.loader_name 75 resource_type_impl 76 end