Class: Puppet::Pops::Loader::TaskInstantiator

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/loader/task_instantiator.rb

Class Method Summary collapse

Class Method Details

.create(loader, typed_name, source_refs) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/puppet/pops/loader/task_instantiator.rb', line 56

def self.create(loader, typed_name, source_refs)
  name = typed_name.name
  basename = typed_name.name_parts[1] || 'init'
  dirname = File.dirname(source_refs[0])
  , executables = source_refs.partition { |source_ref| source_ref.end_with?('.json') }
   = .find { |source_ref| File.basename(source_ref, '.json') == basename }

   = (loader, )

   = validate_implementations(typed_name, dirname, , executables)

  arguments = {
    'name' => name,
    'implementations' => 
  }

  begin
    .each_pair do |key, value|
      if %w[parameters output].include?(key)
        ps = {}
        value.each_pair do |k, v|
          pd = v.dup
          t = v['type']
          pd['type'] = t.nil? ? Types::TypeFactory.data : Types::TypeParser.singleton.parse(t)
          ps[k] = pd
        end
        value = ps
      end
      arguments[key] = value unless arguments.key?(key)
    end

    Types::TypeFactory.task.from_hash(arguments)
  rescue Types::TypeAssertionError => ex
    # Not strictly a parser error but from the users perspective, the file content didn't parse properly. The
    # ParserError also conveys file info (even though line is unknown)
    msg = _('Failed to load metadata for task %{name}: %{reason}') % { name: name, reason: ex.message }
    raise Puppet::ParseError.new(msg, )
  end
end

.load_metadata(loader, metadata) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/puppet/pops/loader/task_instantiator.rb', line 6

def self.(loader, )
  if .nil?
    EMPTY_HASH
  else
    json_text = loader.get_contents()
    begin
      Puppet::Util::Json.load(json_text).freeze || EMPTY_HASH
    rescue Puppet::Util::Json::ParseError => ex
      raise Puppet::ParseError.new(ex.message, )
    end
  end
end

.validate_implementations(typed_name, directory, metadata, executables) ⇒ Object



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
# File 'lib/puppet/pops/loader/task_instantiator.rb', line 19

def self.validate_implementations(typed_name, directory, , executables)
  name = typed_name.name
  basename = typed_name.name_parts[1] || 'init'
  # If 'implementations' is defined, it needs to mention at least one
  # implementation, and everything it mentions must exist.
  if .key?('implementations')
    if ['implementations'].is_a?(Array)
      ['implementations'].map do |impl|
        path = executables.find { |real_impl| File.basename(real_impl) == impl['name'] }
        if path
          { "name" => impl['name'], "requirements" => impl.fetch('requirements', []), "path" => path }
        else
          raise ArgumentError, _("Task metadata for task %{name} specifies missing implementation %{implementation}") %
            { name: name, implementation: impl['name'] }
        end
      end
    else
      # If 'implementations' is the wrong type, we just pass it through and
      # let the task type definition reject it.
      ['implementations']
    end
  # If implementations isn't defined, then we use executables matching the
  # task name, and only one may exist.
  else
    implementations = executables.select { |impl| File.basename(impl, '.*') == basename }
    if implementations.empty?
      raise ArgumentError, _('No source besides task metadata was found in directory %{directory} for task %{name}') %
        { name: name, directory: directory }
    elsif implementations.length > 1
      raise ArgumentError, _("Multiple executables were found in directory %{directory} for task %{name}; define 'implementations' in metadata to differentiate between them") %
        { name: name, directory: implementations[0] }
    end

    [{ "name" => File.basename(implementations.first), "path" => implementations.first, "requirements" => [] }]
  end
end