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/step/eval.rb,
lib/bolt/pal/yaml_plan/step/plan.rb,
lib/bolt/pal/yaml_plan/step/task.rb,
lib/bolt/pal/yaml_plan/transpiler.rb,
lib/bolt/pal/yaml_plan/step/script.rb,
lib/bolt/pal/yaml_plan/step/upload.rb,
lib/bolt/pal/yaml_plan/step/command.rb,
lib/bolt/pal/yaml_plan/step/resources.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

Returns a new instance of 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
# 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.create(stringified_step, index + 1)
    duplicate_check(used_names, stringified_step['name'], index + 1)
    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



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

def body
  self
end

#duplicate_check(used_names, name, step_number) ⇒ Object



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

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

#return_typeObject



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

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.



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

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