Class: Puppet::Pops::Evaluator::DeferredResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/evaluator/deferred_resolver.rb

Overview

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

Constant Summary collapse

DOLLAR =
'$'.freeze
DIG =
'dig'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(compiler, preprocess_deferred = true) ⇒ DeferredResolver

Returns a new instance of DeferredResolver.


66
67
68
69
70
71
72
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 66

def initialize(compiler, preprocess_deferred = true)
  @compiler = compiler
  # Always resolve in top scope
  @scope = @compiler.topscope
  @deferred_class = Puppet::Pops::Types::TypeFactory.deferred.implementation_class
  @preprocess_deferred = preprocess_deferred
end

Class Method Details

.resolve(value, compiler) ⇒ Object

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.

Parameters:

Returns:

  • (Object)

    the resolved value (a new Array, Hash, or Sensitive if needed), with all deferred values resolved


61
62
63
64
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 61

def self.resolve(value, compiler)
  resolver = new(compiler)
  resolver.resolve(value)
end

.resolve_and_replace(facts, catalog, environment = catalog.environment_instance, preprocess_deferred = true) ⇒ nil

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.

Parameters:

Returns:

  • (nil)

    does not return anything - the catalog is modified as a side effect


33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 33

def self.resolve_and_replace(facts, catalog, environment = catalog.environment_instance, preprocess_deferred = true)
  compiler = Puppet::Parser::ScriptCompiler.new(environment, catalog.name, preprocess_deferred)
  resolver = new(compiler, preprocess_deferred)
  resolver.set_facts_variable(facts)
  # TODO:
  #    # When scripting the trusted data are always local, but set them anyway
  #    @scope.set_trusted(node.trusted_data)
  #
  #    # Server facts are always about the local node's version etc.
  #    @scope.set_server_facts(node.server_facts)

  resolver.resolve_futures(catalog)
  nil
end

Instance Method Details

#resolve(x) ⇒ Object


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 100

def resolve(x)
  if x.class == @deferred_class
    resolve_future(x)
  elsif x.is_a?(Array)
    x.map {|v| resolve(v) }
  elsif x.is_a?(Hash)
    result = {}
    x.each_pair {|k,v| result[k] = resolve(v) }
    result
  elsif x.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
    # rewrap in a new Sensitive after resolving any nested deferred values
    Puppet::Pops::Types::PSensitiveType::Sensitive.new(resolve(x.unwrap))
  elsif x.is_a?(Puppet::Pops::Types::PBinaryType::Binary)
    # use the ASCII-8BIT string that it wraps
    x.binary_buffer
  else
    x
  end
end

#resolve_future(f) ⇒ Object


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 138

def resolve_future(f)
  # If any of the arguments to a future is a future it needs to be resolved first
  func_name = f.name
  mapped_arguments = map_arguments(f.arguments)
  # if name starts with $ then this is a call to dig
  if func_name[0] == DOLLAR
    var_name = func_name[1..-1]
    func_name = DIG
    mapped_arguments.insert(0, @scope[var_name])
  end

  if @preprocess_deferred
    # call the function (name in deferred, or 'dig' for a variable)
    @scope.call_function(func_name, mapped_arguments)
  else
    # call the function later
    DeferredValue.new(
      Proc.new {
        # deferred functions can have nested deferred arguments
        resolved_arguments = mapped_arguments.map { |arg| resolve_lazy_args(arg) }
        @scope.call_function(func_name, resolved_arguments)
      }
    )
  end
end

#resolve_futures(catalog) ⇒ Object


80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 80

def resolve_futures(catalog)
  catalog.resources.each do |r|
    overrides = {}
    r.parameters.each_pair do |k, v|
      resolved = resolve(v)
      # If the value is instance of Sensitive - assign the unwrapped value
      # and mark it as sensitive if not already marked
      #
      if resolved.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive)
        resolved = resolved.unwrap
        unless r.sensitive_parameters.include?(k.to_sym)
          r.sensitive_parameters = (r.sensitive_parameters + [k.to_sym]).freeze
        end
      end
      overrides[ k ] = resolved
    end
    r.parameters.merge!(overrides) unless overrides.empty?
  end
end

#set_facts_variable(facts) ⇒ Object

Parameters:


76
77
78
# File 'lib/puppet/pops/evaluator/deferred_resolver.rb', line 76

def set_facts_variable(facts)
  @scope.set_facts(facts.nil? ? {} : facts.values)
end