Class: Bolt::PAL::YamlPlan

Inherits:
Object
  • Object
show all
Defined in:
lib/bolt/pal/yaml_plan.rb,
lib/bolt/pal/yaml_plan/step.rb,
lib/bolt/pal/yaml_plan/loader.rb,
lib/bolt/pal/yaml_plan/evaluator.rb,
lib/bolt/pal/yaml_plan/parameter.rb,
lib/bolt/pal/yaml_plan/transpiler.rb

Defined Under Namespace

Classes: BareString, CodeLiteral, DoubleQuotedString, EvaluableString, Evaluator, Loader, Parameter, Step, Transpiler

Constant Summary collapse

PLAN_KEYS =
Set['parameters', 'steps', 'return', 'version']
VAR_NAME_PATTERN =
/\A[a-z_][a-z0-9_]*\z/.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, plan) ⇒ YamlPlan



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/bolt/pal/yaml_plan.rb', line 14

def initialize(name, plan)
  # Top-level plan keys aren't allowed to be Puppet code, so force them
  # all to strings.
  plan = Bolt::Util.walk_keys(plan) { |key| stringify(key) }
  @name = name.freeze

  params_hash = stringify(plan.fetch('parameters', {}))
  # Ensure params is a hash
  unless params_hash.is_a?(Hash)
    raise Bolt::Error.new("Plan parameters must be a Hash", "bolt/invalid-plan")
  end

  # Munge parameters into an array of Parameter objects, which is what
  # the Puppet API expects
  @parameters = params_hash.map do |param, definition|
    Parameter.new(param, definition)
  end.freeze

  # Validate top level plan keys
  top_level_keys = plan.keys.to_set
  unless PLAN_KEYS.superset?(top_level_keys)
    invalid_keys = top_level_keys - PLAN_KEYS
    raise Bolt::Error.new("Plan contains illegal key(s) #{invalid_keys.to_a.inspect}",
                          "bolt/invalid-plan")
  end

  unless plan['steps'].is_a?(Array)
    raise Bolt::Error.new("Plan must specify an array of steps", "bolt/invalid-plan")
  end

  used_names = Set.new(@parameters.map(&:name))

  @steps = plan['steps'].each_with_index.map do |step, index|
    # Step keys also aren't allowed to be code and neither is the value of "name"
    stringified_step = Bolt::Util.walk_keys(step) { |key| stringify(key) }
    stringified_step['name'] = stringify(stringified_step['name']) if stringified_step.key?('name')

    step = Step.new(stringified_step, index + 1)
    # Send object instead of just name so that step number is printed
    duplicate_check(used_names, step)
    used_names << stringified_step['name'] if stringified_step['name']
    step
  end.freeze
  @return = plan['return']
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'lib/bolt/pal/yaml_plan.rb', line 12

def name
  @name
end

#parametersObject (readonly)

Returns the value of attribute parameters.



12
13
14
# File 'lib/bolt/pal/yaml_plan.rb', line 12

def parameters
  @parameters
end

#returnObject (readonly)

Returns the value of attribute return.



12
13
14
# File 'lib/bolt/pal/yaml_plan.rb', line 12

def return
  @return
end

#stepsObject (readonly)

Returns the value of attribute steps.



12
13
14
# File 'lib/bolt/pal/yaml_plan.rb', line 12

def steps
  @steps
end

Instance Method Details

#bodyObject



68
69
70
# File 'lib/bolt/pal/yaml_plan.rb', line 68

def body
  self
end

#duplicate_check(used_names, step) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/bolt/pal/yaml_plan.rb', line 60

def duplicate_check(used_names, step)
  if used_names.include?(step.name)
    error_message = "Duplicate step name or parameter detected: #{step.name.inspect}"
    err = step.step_err_msg(error_message)
    raise Bolt::Error.new(err, "bolt/invalid-plan")
  end
end

#return_typeObject



72
73
74
# File 'lib/bolt/pal/yaml_plan.rb', line 72

def return_type
  Puppet::Pops::Types::TypeParser.singleton.parse('Boltlib::PlanResult')
end

#stringify(value) ⇒ Object

Turn all “potential” strings in the object into actual strings. Because we interpret bare strings as potential Puppet code, even in places where Puppet code isn’t allowed (like some hash keys), we need to be able to force them back into regular strings, as if we had parsed them normally.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/bolt/pal/yaml_plan.rb', line 81

def stringify(value)
  case value
  when Array
    value.map { |element| stringify(element) }
  when Hash
    value.each_with_object({}) do |(k, v), o|
      o[stringify(k)] = stringify(v)
    end
  when EvaluableString
    value.value
  else
    value
  end
end