class Puppet::Pops::Evaluator::DeferredResolver
Utility class to help resolve instances of Puppet::Pops::Types::PDeferredType::Deferred
Constants
- DIG
- DOLLAR
Public Class Methods
# 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
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
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
# 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
# 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
# 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
@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
# 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
# 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