Class: Bolt::Plugin::Module
  
  
  
  
  
    - Inherits:
- 
      Object
      
        
          - Object
- Bolt::Plugin::Module
 show all
    - Defined in:
- lib/bolt/plugin/module.rb
 
Defined Under Namespace
  
    
  
    
      Classes: InvalidPluginData
    
  
  Instance Attribute Summary collapse
  
  
    
      Class Method Summary
      collapse
    
    
  
    
      Instance Method Summary
      collapse
    
    
      
        - 
  
    
      #extract_task_parameter_schema  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #find_hooks(hook_data)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #handle_deprecated_pkcs7_keys(params)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Raises a deprecation warning if the pkcs7 plugin is using deprecated keys and modifies the keys so they are the correct format. 
 
- 
  
    
      #hooks  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #initialize(mod:, context:, config:, **_opts)  ⇒ Module 
    
    
  
  
  
    constructor
  
  
  
  
  
  
  
    
A new instance of Module. 
 
- 
  
    
      #load_data  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #name  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #process_params(task, opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #process_schema(schema)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #puppet_library(opts, target, apply_prep)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #resolve_reference(opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
These are all the same but are defined explicitly for clarity. 
 
- 
  
    
      #run_hook(hook_name, opts, value = true)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #run_task(task, opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #secret_createkeys(opts = {})  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #secret_decrypt(opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #secret_encrypt(opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #setup  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
This method interacts with the module on disk so it’s separate from initialize. 
 
- 
  
    
      #validate_config(config, config_schema)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #validate_params(task, params)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
- 
  
    
      #validate_resolve_reference(opts)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
  
  Constructor Details
  
    
  
  
    #initialize(mod:, context:, config:, **_opts)  ⇒ Module 
  
  
  
  
    
Returns a new instance of Module.
   
 
  
  
    | 
29
30
31
32
33
34
35
36
37 | # File 'lib/bolt/plugin/module.rb', line 29
def initialize(mod:, context:, config:, **_opts)
  @module = mod
  @config = config
  @context = context
  if @module.name == 'pkcs7'
    @config = handle_deprecated_pkcs7_keys(@config)
  end
end | 
 
  
 
  
    Instance Attribute Details
    
      
      
      
  
  
    #config  ⇒ Object  
  
  
  
  
    
Returns the value of attribute config.
   
 
  
  
    | 
27
28
29 | # File 'lib/bolt/plugin/module.rb', line 27
def config
  @config
end | 
 
    
   
  
    Class Method Details
    
      
  
  
    .load(name, modules, opts)  ⇒ Object 
  
  
  
  
    | 
15
16
17
18
19
20
21
22
23
24
25 | # File 'lib/bolt/plugin/module.rb', line 15
def self.load(name, modules, opts)
  mod = modules[name]
  if mod&.plugin?
    opts[:mod] = mod
    plugin = Bolt::Plugin::Module.new(opts)
    plugin.setup
    plugin
  else
    raise PluginError::Unknown, name
  end
end | 
 
    
   
  
    Instance Method Details
    
      
  
  
    | 
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 | # File 'lib/bolt/plugin/module.rb', line 199
def 
    type_set = @hook_map.each_with_object({}) do |(_hook, task), acc|
    next unless (schema = task['task'].metadata['parameters'])
    schema.each do |param, scheme|
      next unless scheme['type'].is_a?(String)
      scheme['type'] = Set.new([scheme['type']])
      if acc.dig(param, 'type').is_a?(Set)
        scheme['type'].merge(acc[param]['type'])
      end
    end
    acc.merge!(schema)
  end
    type_set.each do |_param, schema|
    next unless schema['type']
    schema['type'] = if schema['type'].size > 1
                       "Optional[Variant[#{schema['type'].to_a.join(', ')}]]"
                     else
                       "Optional[#{schema['type'].to_a.first}]"
                     end
  end
end | 
 
    
      
  
  
    #find_hooks(hook_data)  ⇒ Object 
  
  
  
  
    | 
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 | # File 'lib/bolt/plugin/module.rb', line 114
def find_hooks(hook_data)
  raise InvalidPluginData.new("'hooks' must be a hash", name) unless hook_data.is_a?(Hash)
  hooks = {}
    hook_data.each do |hook_name, hook_spec|
    unless hook_spec.is_a?(Hash) && hook_spec['task'].is_a?(String)
      msg = "Unexpected hook specification #{hook_spec.to_json} in #{@name} for hook #{hook_name}"
      raise InvalidPluginData.new(msg, name)
    end
    begin
      task = @context.get_validated_task(hook_spec['task'])
    rescue Bolt::Error => e
      msg = if e.kind == 'bolt/unknown-task'
              "Plugin #{name} specified an unkown task '#{hook_spec['task']}' for a hook"
            else
              "Plugin #{name} could not load task '#{hook_spec['task']}': #{e.message}"
            end
      raise InvalidPluginData.new(msg, name)
    end
    hooks[hook_name.to_sym] = { 'task' => task }
  end
    (Set.new(KNOWN_HOOKS.map) - hooks.keys).each do |hook_name|
    task_name = "#{name}::#{hook_name}"
    begin
      task = @context.get_validated_task(task_name)
    rescue Bolt::Error => e
      raise e unless e.kind == 'bolt/unknown-task'
    end
    hooks[hook_name] = { 'task' => task } if task
  end
  Bolt::Util.symbolize_top_level_keys(hooks)
end | 
 
    
      
  
  
    #handle_deprecated_pkcs7_keys(params)  ⇒ Object 
  
  
  
  
    
Raises a deprecation warning if the pkcs7 plugin is using deprecated keys and modifies the keys so they are the correct format
   
 
  
  
    | 
186
187
188
189
190
191
192
193
194
195
196
197 | # File 'lib/bolt/plugin/module.rb', line 186
def handle_deprecated_pkcs7_keys(params)
  if params.key?('private-key') || params.key?('public-key')
    message = "pkcs7 keys 'private-key' and 'public-key' have been deprecated and will be "\
              "removed in a future version of Bolt; use 'private_key' and 'public_key' instead."
    Bolt::Logger.deprecation_warning('PKCS7 keys using hyphens, not underscores', message)
  end
  params['private_key'] = params.delete('private-key') if params.key?('private-key')
  params['public_key'] = params.delete('public-key') if params.key?('public-key')
  params
end | 
 
    
      
  
  
    #hooks  ⇒ Object 
  
  
  
  
    | 
62
63
64 | # File 'lib/bolt/plugin/module.rb', line 62
def hooks
  (@hook_map.keys + [:validate_resolve_reference]).uniq
end | 
 
    
      
  
  
    #load_data  ⇒ Object 
  
  
  
  
    | 
66
67
68
69
70 | # File 'lib/bolt/plugin/module.rb', line 66
def load_data
  JSON.parse(File.read(@module.plugin_data_file))
rescue JSON::ParserError => e
  raise InvalidPluginData.new(e.message, name)
end | 
 
    
      
  
  
    #name  ⇒ Object 
  
  
  
  
    | 
58
59
60 | # File 'lib/bolt/plugin/module.rb', line 58
def name
  @module.name
end | 
 
    
      
  
  
    #process_params(task, opts)  ⇒ Object 
  
  
  
  
    | 
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 | # File 'lib/bolt/plugin/module.rb', line 157
def process_params(task, opts)
        meta, params = opts.partition { |key, _val| key.start_with?('_') }.map(&:to_h)
  if task.module_name == 'pkcs7'
    params = handle_deprecated_pkcs7_keys(params)
  end
      params = if task.parameters
             task.parameter_defaults
                 .merge(config.slice(*task.parameters.keys))
                 .merge(params)
           else
             config.merge(params)
           end
  validate_params(task, params)
  meta['_boltdir'] = @context.boltdir.to_s
  [params, meta]
end | 
 
    
      
  
  
    #process_schema(schema)  ⇒ Object 
  
  
  
  
    | 
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 | # File 'lib/bolt/plugin/module.rb', line 72
def process_schema(schema)
  raise InvalidPluginData.new('config specification is not an object', name) unless schema.is_a?(Hash)
  schema.each do |key, val|
    unless key =~ /\A[a-z][a-z0-9_]*\z/
      raise InvalidPluginData.new("config specification key, '#{key}',  is not allowed", name)
    end
    unless val.is_a?(Hash) && (val['type'] || '').is_a?(String)
      raise InvalidPluginData.new("config specification #{val.to_json} is not allowed", name)
    end
    type_string = val['type'] || 'Any'
    begin
      val['pcore_type'] = Puppet::Pops::Types::TypeParser.singleton.parse(type_string)
      if val['pcore_type'].is_a? Puppet::Pops::Types::PTypeReferenceType
        raise InvalidPluginData.new("Could not find type '#{type_string}' for #{key}", name)
      end
    rescue Puppet::ParseError
      raise InvalidPluginData.new("Could not parse type '#{type_string}' for #{key}", name)
    end
  end
  schema
end | 
 
    
      
  
  
    #puppet_library(opts, target, apply_prep)  ⇒ Object 
  
  
  
  
    | 
285
286
287
288
289
290
291
292
293
294
295
296 | # File 'lib/bolt/plugin/module.rb', line 285
def puppet_library(opts, target, apply_prep)
  task = @hook_map[:puppet_library]['task']
  params, meta_params = process_params(task, opts)
  options = {}
  options[:run_as] = meta_params['_run_as'] if meta_params['_run_as']
  proc do
    apply_prep.run_task([target], task, params, options).first
  end
end | 
 
    
      
  
  
    #resolve_reference(opts)  ⇒ Object 
  
  
  
  
    
These are all the same but are defined explicitly for clarity
   
 
  
  
    | 
269
270
271 | # File 'lib/bolt/plugin/module.rb', line 269
def resolve_reference(opts)
  run_hook(__method__, opts)
end | 
 
    
      
  
  
    #run_hook(hook_name, opts, value = true)  ⇒ Object 
  
  
  
  
    | 
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 | # File 'lib/bolt/plugin/module.rb', line 239
def run_hook(hook_name, opts, value = true)
  hook = @hook_map[hook_name]
    raise PluginError::UnsupportedHook.new(name, hook_name) unless hook
  result = run_task(hook['task'], opts)
  if value
    unless result.include?('value')
      msg = "Plugin #{name} result did not include a value, got #{result}"
      raise Bolt::Plugin::PluginError::ExecutionError.new(msg, name, hook_name)
    end
    result['value']
  end
end | 
 
    
      
  
  
    #run_task(task, opts)  ⇒ Object 
  
  
  
  
    | 
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 | # File 'lib/bolt/plugin/module.rb', line 223
def run_task(task, opts)
  opts = opts.reject { |key, _val| key.start_with?('_') }
  params, metaparams = process_params(task, opts)
  params = params.merge(metaparams)
    options = { catch_errors: true }
  result = @context.run_local_task(task,
                                   params,
                                   options).first
  raise Bolt::Error.new(result.error_hash['msg'], result.error_hash['kind']) unless result.ok
  result.value
end | 
 
    
      
  
  
    #secret_createkeys(opts = {})  ⇒ Object 
  
  
  
  
    | 
281
282
283 | # File 'lib/bolt/plugin/module.rb', line 281
def secret_createkeys(opts = {})
  run_hook(__method__, opts)
end | 
 
    
      
  
  
    #secret_decrypt(opts)  ⇒ Object 
  
  
  
  
    | 
277
278
279 | # File 'lib/bolt/plugin/module.rb', line 277
def secret_decrypt(opts)
  run_hook(__method__, opts)
end | 
 
    
      
  
  
    #secret_encrypt(opts)  ⇒ Object 
  
  
  
  
    | 
273
274
275 | # File 'lib/bolt/plugin/module.rb', line 273
def secret_encrypt(opts)
  run_hook(__method__, opts)
end | 
 
    
      
  
  
    #setup  ⇒ Object 
  
  
  
  
    
This method interacts with the module on disk so it’s separate from initialize
   
 
  
  
    | 
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 | # File 'lib/bolt/plugin/module.rb', line 40
def setup
  @data = load_data
  @hook_map = find_hooks(@data['hooks'] || {})
  if @data['config']
    msg = <<~MSG.chomp
      Found unsupported key 'config' in bolt_plugin.json. Config for a plugin is inferred
      from task parameters, with config values passed as parameters.
    MSG
    raise InvalidPluginData.new(msg, name)
  end
    @config_schema = process_schema()
  validate_config(@config, @config_schema)
end | 
 
    
      
  
  
    #validate_config(config, config_schema)  ⇒ Object 
  
  
  
  
    | 
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | # File 'lib/bolt/plugin/module.rb', line 97
def validate_config(config, config_schema)
  config.each_key do |key|
    msg = "Config for #{name} plugin contains unexpected key #{key}"
    raise Bolt::ValidationError, msg unless config_schema.include?(key)
  end
  config_schema.each do |key, spec|
    val = config[key]
    unless spec['pcore_type'].instance?(val)
      raise Bolt::ValidationError, "#{name} plugin expects a #{spec['type']} for key #{key}, got: #{val}"
    end
    val.nil?
  end
  nil
end | 
 
    
      
  
  
    #validate_params(task, params)  ⇒ Object 
  
  
  
  
    | 
153
154
155 | # File 'lib/bolt/plugin/module.rb', line 153
def validate_params(task, params)
  @context.validate_params(task.name, params)
end | 
 
    
      
  
  
    #validate_resolve_reference(opts)  ⇒ Object 
  
  
  
  
    | 
255
256
257
258
259
260
261
262
263
264
265
266 | # File 'lib/bolt/plugin/module.rb', line 255
def validate_resolve_reference(opts)
  task = @hook_map[:resolve_reference]['task']
  params, _metaparams = process_params(task, opts)
  if task
    validate_params(task, params)
  end
  if @hook_map.include?(:validate_resolve_reference)
    run_hook(:validate_resolve_reference, opts, false)
  end
end |