lib/bolt/applicator.rb in bolt-0.21.4 vs lib/bolt/applicator.rb in bolt-0.21.5

- old
+ new

@@ -1,11 +1,14 @@ # frozen_string_literal: true +require 'base64' +require 'concurrent' +require 'find' require 'json' require 'logging' +require 'minitar' require 'open3' -require 'concurrent' require 'bolt/util/puppet_log_level' module Bolt Task = Struct.new(:name, :implementations, :input_method) @@ -17,16 +20,32 @@ @pdb_client = pdb_client @hiera_config = hiera_config ? validate_hiera_config(hiera_config) : nil @pool = Concurrent::ThreadPoolExecutor.new(max_threads: max_compiles) @logger = Logging.logger[self] + @plugin_tarball = Concurrent::Delay.new do + build_plugin_tarball do |mod| + search_dirs = [] + search_dirs << mod.plugins if mod.plugins? + search_dirs << mod.files if mod.files? + search_dirs + end + end end private def libexec @libexec ||= File.join(Gem::Specification.find_by_name('bolt').gem_dir, 'libexec') end + def custom_facts_task + @custom_facts_task ||= begin + path = File.join(libexec, 'custom_facts.rb') + impl = { 'name' => 'custom_facts.rb', 'path' => path, 'requirements' => [], 'supports_noop' => true } + Task.new('custom_facts', [impl], 'stdin') + end + end + def catalog_apply_task @catalog_apply_task ||= begin path = File.join(libexec, 'apply_catalog.rb') impl = { 'name' => 'apply_catalog.rb', 'path' => path, 'requirements' => [], 'supports_noop' => true } Task.new('apply_catalog', [impl], 'stdin') @@ -44,15 +63,15 @@ target: { name: target.host, facts: @inventory.facts(target), variables: @inventory.vars(target).merge(plan_vars), trusted: trusted.to_h - } + }, + inventory: @inventory.data_hash } bolt_catalog_exe = File.join(libexec, 'bolt_catalog') - old_path = ENV['PATH'] ENV['PATH'] = "#{RbConfig::CONFIG['bindir']}#{File::PATH_SEPARATOR}#{old_path}" out, err, stat = Open3.capture3('ruby', bolt_catalog_exe, 'compile', stdin_data: catalog_input.to_json) ENV['PATH'] = old_path @@ -142,10 +161,12 @@ def apply(args, apply_body, scope) raise(ArgumentError, 'apply requires a TargetSpec') if args.empty? type0 = Puppet.lookup(:pal_script_compiler).type('TargetSpec') Puppet::Pal.assert_type(type0, args[0], 'apply targets') + @executor.report_function_call('apply') + options = {} if args.count > 1 type1 = Puppet.lookup(:pal_script_compiler).type('Hash[String, Data]') Puppet::Pal.assert_type(type1, args[1], 'apply options') options = args[1] @@ -169,11 +190,11 @@ end result_promises = targets.zip(futures).flat_map do |target, future| @executor.queue_execute([target]) do |transport, batch| @executor.with_node_logging("Applying manifest block", batch) do - arguments = { 'catalog' => future.value, '_noop' => options['_noop'] } + arguments = { 'catalog' => future.value, 'plugins' => plugins, '_noop' => options['_noop'] } raise future.reason if future.rejected? result = transport.batch_task(batch, catalog_apply_task, arguments, options, &notify) result = provide_puppet_missing_errors(result) identify_resource_failures(result) end @@ -185,8 +206,48 @@ if !r.ok && !options['_catch_errors'] raise Bolt::ApplyFailure, r end r + end + + def plugins + @plugin_tarball.value || + raise(Bolt::Error.new("Failed to pack module plugins: #{@plugin_tarball.reason}", 'bolt/plugin-error')) + end + + def build_plugin_tarball + start_time = Time.now + sio = StringIO.new + output = Minitar::Output.new(Zlib::GzipWriter.new(sio)) + + Puppet.lookup(:current_environment).modules.each do |mod| + search_dirs = yield mod + + parent = Pathname.new(mod.path).parent + files = Find.find(*search_dirs).select { |file| File.file?(file) } + + files.each do |file| + tar_path = Pathname.new(file).relative_path_from(parent) + @logger.debug("Packing plugin #{file} to #{tar_path}") + stat = File.stat(file) + content = File.binread(file) + output.tar.add_file_simple( + tar_path.to_s, + data: content, + size: content.size, + mode: stat.mode & 0o777, + mtime: stat.mtime + ) + end + end + + duration = Time.now - start_time + @logger.debug("Packed plugins in #{duration * 1000} ms") + + output.close + Base64.encode64(sio.string) + ensure + output&.close end end end