class Puppet::Pops::Evaluator::DeferredResolver

Utility class to help resolve instances of Puppet::Pops::Types::PDeferredType::Deferred

Constants

DIG
DOLLAR

Public Class Methods

new(compiler, preprocess_deferred = true) click to toggle source
   # File lib/puppet/pops/evaluator/deferred_resolver.rb
67 def initialize(compiler, preprocess_deferred = true)
68   @compiler = compiler
69   # Always resolve in top scope
70   @scope = @compiler.topscope
71   @deferred_class = Puppet::Pops::Types::TypeFactory.deferred.implementation_class
72   @preprocess_deferred = preprocess_deferred
73 end
resolve(value, compiler) click to toggle source

Resolves a value such that a direct Deferred, or any nested Deferred values are resolved and used instead of the deferred value. A direct Deferred value, or nested deferred values inside of Array, Hash or Sensitive values are resolved and replaced inside of freshly created containers.

The resolution takes place in the topscope of the given compiler. Variable values are supposed to already have been set.

@param value [Object] the (possibly nested) value to resolve @param compiler [Puppet::Parser::ScriptCompiler, Puppet::Parser::Compiler] the compiler in effect @return [Object] the resolved value (a new Array, Hash, or Sensitive if needed), with all deferred values resolved

   # File lib/puppet/pops/evaluator/deferred_resolver.rb
62 def self.resolve(value, compiler)
63   resolver = new(compiler)
64   resolver.resolve(value)
65 end
resolve_and_replace(facts, catalog, environment = catalog.environment_instance, preprocess_deferred = true) click to toggle source

Resolves and replaces all Deferred values in a catalog's resource attributes found as direct values or nested inside Array, Hash or Sensitive values. Deferred values inside of custom Object instances are not resolved as this is expected to be done by such objects.

@param facts [Puppet::Node::Facts] the facts object for the node @param catalog [Puppet::Resource::Catalog] the catalog where all deferred values should be replaced @param environment [Puppet::Node::Environment] the environment whose anonymous module methods

are to be mixed into the scope

@return [nil] does not return anything - the catalog is modified as a side effect

   # File lib/puppet/pops/evaluator/deferred_resolver.rb
34 def self.resolve_and_replace(facts, catalog, environment = catalog.environment_instance, preprocess_deferred = true)
35   compiler = Puppet::Parser::ScriptCompiler.new(environment, catalog.name, preprocess_deferred)
36   resolver = new(compiler, preprocess_deferred)
37   resolver.set_facts_variable(facts)
38   # TODO:
39   #    # When scripting the trusted data are always local, but set them anyway
40   #    @scope.set_trusted(node.trusted_data)
41   #
42   #    # Server facts are always about the local node's version etc.
43   #    @scope.set_server_facts(node.server_facts)
44 
45   resolver.resolve_futures(catalog)
46   nil
47 end

Public Instance Methods

resolve(x) click to toggle source
    # File lib/puppet/pops/evaluator/deferred_resolver.rb
101 def resolve(x)
102   if x.class == @deferred_class
103     resolve_future(x)
104   elsif x.is_a?(Array)
105     x.map {|v| resolve(v) }
106   elsif x.is_a?(Hash)
107     result = {}
108     x.each_pair {|k,v| result[k] = resolve(v) }
109     result
110   elsif x.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
111     # rewrap in a new Sensitive after resolving any nested deferred values
112     Puppet::Pops::Types::PSensitiveType::Sensitive.new(resolve(x.unwrap))
113   elsif x.is_a?(Puppet::Pops::Types::PBinaryType::Binary)
114     # use the ASCII-8BIT string that it wraps
115     x.binary_buffer
116   else
117     x
118   end
119 end
resolve_future(f) click to toggle source
    # File lib/puppet/pops/evaluator/deferred_resolver.rb
139 def resolve_future(f)
140   # If any of the arguments to a future is a future it needs to be resolved first
141   func_name = f.name
142   mapped_arguments = map_arguments(f.arguments)
143   # if name starts with $ then this is a call to dig
144   if func_name[0] == DOLLAR
145     var_name = func_name[1..-1]
146     func_name = DIG
147     mapped_arguments.insert(0, @scope[var_name])
148   end
149 
150   if @preprocess_deferred
151     # call the function (name in deferred, or 'dig' for a variable)
152     @scope.call_function(func_name, mapped_arguments)
153   else
154     # call the function later
155     DeferredValue.new(
156       Proc.new {
157         # deferred functions can have nested deferred arguments
158         resolved_arguments = mapped_arguments.map { |arg| resolve_lazy_args(arg) }
159         @scope.call_function(func_name, resolved_arguments)
160       }
161     )
162   end
163 end
resolve_futures(catalog) click to toggle source
   # File lib/puppet/pops/evaluator/deferred_resolver.rb
81 def resolve_futures(catalog)
82   catalog.resources.each do |r|
83     overrides = {}
84     r.parameters.each_pair do |k, v|
85       resolved = resolve(v)
86       # If the value is instance of Sensitive - assign the unwrapped value
87       # and mark it as sensitive if not already marked
88       #
89       if resolved.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
90         resolved = resolved.unwrap
91         unless r.sensitive_parameters.include?(k.to_sym)
92           r.sensitive_parameters = (r.sensitive_parameters + [k.to_sym]).freeze
93         end
94       end
95       overrides[ k ] = resolved
96     end
97     r.parameters.merge!(overrides) unless overrides.empty?
98   end
99 end
set_facts_variable(facts) click to toggle source

@param facts [Puppet::Node::Facts] the facts to set in $facts in the compiler's topscope

   # File lib/puppet/pops/evaluator/deferred_resolver.rb
77 def set_facts_variable(facts)
78   @scope.set_facts(facts.nil? ? {} : facts.values)
79 end

Private Instance Methods

map_arguments(args) click to toggle source
    # File lib/puppet/pops/evaluator/deferred_resolver.rb
165 def map_arguments(args)
166   return [] if args.nil?
167   args.map {|v| resolve(v) }
168 end
resolve_lazy_args(x) click to toggle source
    # File lib/puppet/pops/evaluator/deferred_resolver.rb
121 def resolve_lazy_args(x)
122   if x.is_a?(DeferredValue)
123     x.resolve
124   elsif x.is_a?(Array)
125     x.map {|v| resolve_lazy_args(v) }
126   elsif x.is_a?(Hash)
127     result = {}
128     x.each_pair {|k,v| result[k] = resolve_lazy_args(v) }
129     result
130   elsif x.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
131     # rewrap in a new Sensitive after resolving any nested deferred values
132     Puppet::Pops::Types::PSensitiveType::Sensitive.new(resolve_lazy_args(x.unwrap))
133   else
134     x
135   end
136 end