Class: Bolt::PAL::YamlPlan::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/bolt/pal/yaml_plan/evaluator.rb

Instance Method Summary collapse

Constructor Details

#initialize(analytics = Bolt::Analytics::NoopClient.new) ⇒ Evaluator

Returns a new instance of Evaluator.


9
10
11
12
13
# File 'lib/bolt/pal/yaml_plan/evaluator.rb', line 9

def initialize(analytics = Bolt::Analytics::NoopClient.new)
  @logger = Bolt::Logger.logger(self)
  @analytics = analytics
  @evaluator = Puppet::Pops::Parser::EvaluatingParser.new
end

Instance Method Details

#evaluate(value, _scope) ⇒ Object

Occasionally the Closure will ask us to evaluate what it assumes are AST objects. Because we've sidestepped the AST, they aren't, so just return the values as already evaluated.


59
60
61
# File 'lib/bolt/pal/yaml_plan/evaluator.rb', line 59

def evaluate(value, _scope)
  value
end

#evaluate_block_with_bindings(closure_scope, args_hash, plan) ⇒ Object

This is the method that Puppet calls to evaluate the plan. The name makes more sense for .pp plans.


18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/bolt/pal/yaml_plan/evaluator.rb', line 18

def evaluate_block_with_bindings(closure_scope, args_hash, plan)
  plan_result = closure_scope.with_local_scope(args_hash) do |scope|
    plan.steps.each do |step|
      step_result = step.evaluate(scope, self)

      scope.setvar(step.body['name'], step_result) if step.body['name']
    end

    evaluate_code_blocks(scope, plan.return)
  end

  throw :return, Puppet::Pops::Evaluator::Return.new(plan_result, nil, nil)
end

#evaluate_code_blocks(scope, value) ⇒ Object

Recursively evaluate any EvaluableString instances in the object.


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/bolt/pal/yaml_plan/evaluator.rb', line 34

def evaluate_code_blocks(scope, value)
  # XXX We should establish a local scope here probably
  case value
  when Array
    value.map { |element| evaluate_code_blocks(scope, element) }
  when Hash
    value.each_with_object({}) do |(k, v), o|
      key = k.is_a?(EvaluableString) ? k.value : k
      o[key] = evaluate_code_blocks(scope, v)
    end
  when EvaluableString
    begin
      value.evaluate(scope, @evaluator)
    rescue StandardError => e
      raise format_evaluate_error(e, value)
    end
  else
    value
  end
end

#format_evaluate_error(error, value) ⇒ Object


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/bolt/pal/yaml_plan/evaluator.rb', line 63

def format_evaluate_error(error, value)
  # The Puppet::PreformattedError includes the line number of the
  # evaluable string that caused the error, while the value includes the
  # line number of the YAML plan that the string began on. To get the
  # actual line number of the error, add these two numbers together.
  line = error.line + value.line

  # If the evaluable string is not a scalar literal, correct for it
  # being on the same line as the step key.
  line -= 1 if value.is_a?(BareString)

  Bolt::PlanFailure.new(
    error.basic_message,
    'bolt/evaluation-error',
    { file: value.file, line: line }
  )
end