bolt 3.7.1 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Puppetfile +3 -3
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +5 -1
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +5 -1
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +9 -3
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +6 -2
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +8 -3
- data/lib/bolt/applicator.rb +1 -1
- data/lib/bolt/bolt_option_parser.rb +22 -0
- data/lib/bolt/catalog.rb +2 -1
- data/lib/bolt/cli.rb +65 -27
- data/lib/bolt/outputter/human.rb +8 -4
- data/lib/bolt/outputter/json.rb +4 -0
- data/lib/bolt/pal.rb +45 -0
- data/lib/bolt/result.rb +5 -0
- data/lib/bolt/util.rb +60 -0
- data/lib/bolt/version.rb +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 1f4c856f3322c88dabb51efe39bc7373d96e33f6274785188900e8fbb5488436
         | 
| 4 | 
            +
              data.tar.gz: 5e5da3f150093febfc2b6d7e343e9995ea33b044fb4941ed9229944e4735aa72
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 8f88f29b98a7bab28a4bbae5e860bb4c94fca20dd994241b71f2e5327934a92db1370c77fdb03d5f9a033e626b726e379e3eec510f0316b67b0807aa86920b67
         | 
| 7 | 
            +
              data.tar.gz: 8cf9a3bbfde78b7930089a7ada109e03bba5439ea8ef3049d3fa58bc589914881969be783fe667ef5c238613e126c7f79d7dd0db30fcd2f5d9147999086d1df7
         | 
    
        data/Puppetfile
    CHANGED
    
    | @@ -6,7 +6,7 @@ moduledir File.join(File.dirname(__FILE__), 'modules') | |
| 6 6 |  | 
| 7 7 | 
             
            # Core modules used by 'apply'
         | 
| 8 8 | 
             
            mod 'puppetlabs-service', '2.0.0'
         | 
| 9 | 
            -
            mod 'puppetlabs-puppet_agent', '4. | 
| 9 | 
            +
            mod 'puppetlabs-puppet_agent', '4.6.1'
         | 
| 10 10 | 
             
            mod 'puppetlabs-facts', '1.4.0'
         | 
| 11 11 |  | 
| 12 12 | 
             
            # Core types and providers for Puppet 6
         | 
| @@ -17,7 +17,7 @@ mod 'puppetlabs-sshkeys_core', '2.2.0' | |
| 17 17 | 
             
            mod 'puppetlabs-zfs_core', '1.2.0'
         | 
| 18 18 | 
             
            mod 'puppetlabs-cron_core', '1.0.5'
         | 
| 19 19 | 
             
            mod 'puppetlabs-mount_core', '1.0.4'
         | 
| 20 | 
            -
            mod 'puppetlabs-selinux_core', '1.0 | 
| 20 | 
            +
            mod 'puppetlabs-selinux_core', '1.1.0'
         | 
| 21 21 | 
             
            mod 'puppetlabs-yumrepo_core', '1.0.7'
         | 
| 22 22 | 
             
            mod 'puppetlabs-zone_core', '1.0.3'
         | 
| 23 23 |  | 
| @@ -29,7 +29,7 @@ mod 'puppetlabs-python_task_helper', '0.5.0' | |
| 29 29 | 
             
            mod 'puppetlabs-reboot', '4.0.2'
         | 
| 30 30 | 
             
            mod 'puppetlabs-ruby_task_helper', '0.6.0'
         | 
| 31 31 | 
             
            mod 'puppetlabs-ruby_plugin_helper', '0.2.0'
         | 
| 32 | 
            -
            mod 'puppetlabs-stdlib', '7.0. | 
| 32 | 
            +
            mod 'puppetlabs-stdlib', '7.0.1'
         | 
| 33 33 |  | 
| 34 34 | 
             
            # Plugin modules
         | 
| 35 35 | 
             
            mod 'puppetlabs-aws_inventory', '0.7.0'
         | 
| @@ -108,7 +108,11 @@ Puppet::Functions.create_function(:run_script, Puppet::Functions::InternalFuncti | |
| 108 108 | 
             
                # Send Analytics Report
         | 
| 109 109 | 
             
                executor.report_function_call(self.class.name)
         | 
| 110 110 |  | 
| 111 | 
            -
                 | 
| 111 | 
            +
                future = executor&.future || {}
         | 
| 112 | 
            +
                fallback = future.fetch('file_paths', false)
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                # Find the file path if it exists, otherwise return nil
         | 
| 115 | 
            +
                found = Bolt::Util.find_file_from_scope(script, scope, fallback)
         | 
| 112 116 | 
             
                unless found && Puppet::FileSystem.exist?(found)
         | 
| 113 117 | 
             
                  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
         | 
| 114 118 | 
             
                    Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: script
         | 
| @@ -70,7 +70,11 @@ Puppet::Functions.create_function(:upload_file, Puppet::Functions::InternalFunct | |
| 70 70 | 
             
                # Send Analytics Report
         | 
| 71 71 | 
             
                executor.report_function_call(self.class.name)
         | 
| 72 72 |  | 
| 73 | 
            -
                 | 
| 73 | 
            +
                future = executor&.future || {}
         | 
| 74 | 
            +
                fallback = future.fetch('file_paths', false)
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                # Find the file path if it exists, otherwise return nil
         | 
| 77 | 
            +
                found = Bolt::Util.find_file_from_scope(source, scope, fallback)
         | 
| 74 78 | 
             
                unless found && Puppet::FileSystem.exist?(found)
         | 
| 75 79 | 
             
                  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
         | 
| 76 80 | 
             
                    Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: source
         | 
| @@ -12,14 +12,20 @@ Puppet::Functions.create_function(:'file::exists', Puppet::Functions::InternalFu | |
| 12 12 | 
             
              #   file::exists('example/VERSION')
         | 
| 13 13 | 
             
              dispatch :exists do
         | 
| 14 14 | 
             
                scope_param
         | 
| 15 | 
            -
                required_param 'String', :filename
         | 
| 15 | 
            +
                required_param 'String[1]', :filename
         | 
| 16 16 | 
             
                return_type 'Boolean'
         | 
| 17 17 | 
             
              end
         | 
| 18 18 |  | 
| 19 19 | 
             
              def exists(scope, filename)
         | 
| 20 20 | 
             
                # Send Analytics Report
         | 
| 21 | 
            -
                Puppet.lookup(:bolt_executor) {} | 
| 22 | 
            -
                 | 
| 21 | 
            +
                executor = Puppet.lookup(:bolt_executor) {}
         | 
| 22 | 
            +
                executor&.report_function_call(self.class.name)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                future = executor&.future || Puppet.lookup(:future) || {}
         | 
| 25 | 
            +
                fallback = future.fetch('file_paths', false)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # Find the file path if it exists, otherwise return nil
         | 
| 28 | 
            +
                found = Bolt::Util.find_file_from_scope(filename, scope, fallback)
         | 
| 23 29 | 
             
                found ? Puppet::FileSystem.exist?(found) : false
         | 
| 24 30 | 
             
              end
         | 
| 25 31 | 
             
            end
         | 
| @@ -11,7 +11,7 @@ Puppet::Functions.create_function(:'file::read', Puppet::Functions::InternalFunc | |
| 11 11 | 
             
              #   file::read('example/VERSION')
         | 
| 12 12 | 
             
              dispatch :read do
         | 
| 13 13 | 
             
                scope_param
         | 
| 14 | 
            -
                required_param 'String', :filename
         | 
| 14 | 
            +
                required_param 'String[1]', :filename
         | 
| 15 15 | 
             
                return_type 'String'
         | 
| 16 16 | 
             
              end
         | 
| 17 17 |  | 
| @@ -20,7 +20,11 @@ Puppet::Functions.create_function(:'file::read', Puppet::Functions::InternalFunc | |
| 20 20 | 
             
                executor = Puppet.lookup(:bolt_executor) {}
         | 
| 21 21 | 
             
                executor&.report_function_call(self.class.name)
         | 
| 22 22 |  | 
| 23 | 
            -
                 | 
| 23 | 
            +
                future = executor&.future || Puppet.lookup(:future) || {}
         | 
| 24 | 
            +
                fallback = future.fetch('file_paths', false)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # Find the file path if it exists, otherwise return nil
         | 
| 27 | 
            +
                found = Bolt::Util.find_file_from_scope(filename, scope, fallback)
         | 
| 24 28 | 
             
                unless found && Puppet::FileSystem.exist?(found)
         | 
| 25 29 | 
             
                  raise Puppet::ParseErrorWithIssue.from_issue_and_stack(
         | 
| 26 30 | 
             
                    Puppet::Pops::Issues::NO_SUCH_FILE_OR_DIRECTORY, file: filename
         | 
| @@ -12,15 +12,20 @@ Puppet::Functions.create_function(:'file::readable', Puppet::Functions::Internal | |
| 12 12 | 
             
              #   file::readable('example/VERSION')
         | 
| 13 13 | 
             
              dispatch :readable do
         | 
| 14 14 | 
             
                scope_param
         | 
| 15 | 
            -
                required_param 'String', :filename
         | 
| 15 | 
            +
                required_param 'String[1]', :filename
         | 
| 16 16 | 
             
                return_type 'Boolean'
         | 
| 17 17 | 
             
              end
         | 
| 18 18 |  | 
| 19 19 | 
             
              def readable(scope, filename)
         | 
| 20 20 | 
             
                # Send Analytics Report
         | 
| 21 | 
            -
                Puppet.lookup(:bolt_executor) {} | 
| 21 | 
            +
                executor = Puppet.lookup(:bolt_executor) {}
         | 
| 22 | 
            +
                executor&.report_function_call(self.class.name)
         | 
| 22 23 |  | 
| 23 | 
            -
                 | 
| 24 | 
            +
                future = executor&.future || Puppet.lookup(:future) || {}
         | 
| 25 | 
            +
                fallback = future.fetch('file_paths', false)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # Find the file path if it exists, otherwise return nil
         | 
| 28 | 
            +
                found = Bolt::Util.find_file_from_scope(filename, scope, fallback)
         | 
| 24 29 | 
             
                found ? File.readable?(found) : false
         | 
| 25 30 | 
             
              end
         | 
| 26 31 | 
             
            end
         | 
    
        data/lib/bolt/applicator.rb
    CHANGED
    
    | @@ -87,7 +87,7 @@ module Bolt | |
| 87 87 | 
             
                    variables: @inventory.vars(target),
         | 
| 88 88 | 
             
                    trusted: trusted.to_h
         | 
| 89 89 | 
             
                  }
         | 
| 90 | 
            -
                  catalog_request = scope.merge(target: target_data)
         | 
| 90 | 
            +
                  catalog_request = scope.merge(target: target_data).merge(future: @executor.future || {})
         | 
| 91 91 |  | 
| 92 92 | 
             
                  bolt_catalog_exe = File.join(libexec, 'bolt_catalog')
         | 
| 93 93 | 
             
                  old_path = ENV['PATH']
         | 
| @@ -66,6 +66,9 @@ module Bolt | |
| 66 66 | 
             
                  when 'guide'
         | 
| 67 67 | 
             
                    { flags: OPTIONS[:global] + %w[format],
         | 
| 68 68 | 
             
                      banner: GUIDE_HELP }
         | 
| 69 | 
            +
                  when 'lookup'
         | 
| 70 | 
            +
                    { flags: ACTION_OPTS + %w[hiera-config],
         | 
| 71 | 
            +
                      banner: LOOKUP_HELP }
         | 
| 69 72 | 
             
                  when 'module'
         | 
| 70 73 | 
             
                    case action
         | 
| 71 74 | 
             
                    when 'add'
         | 
| @@ -187,6 +190,7 @@ module Bolt | |
| 187 190 | 
             
                      guide             View guides for Bolt concepts and features
         | 
| 188 191 | 
             
                      inventory         Show the list of targets an action would run on
         | 
| 189 192 | 
             
                      module            Manage Bolt project modules
         | 
| 193 | 
            +
                      lookup            Look up a value with Hiera
         | 
| 190 194 | 
             
                      plan              Convert, create, show, and run Bolt plans
         | 
| 191 195 | 
             
                      project           Create and migrate Bolt projects
         | 
| 192 196 | 
             
                      script            Upload a local script and run it remotely
         | 
| @@ -398,6 +402,24 @@ module Bolt | |
| 398 402 | 
             
                      To learn more about the inventory run 'bolt guide inventory'.
         | 
| 399 403 | 
             
                HELP
         | 
| 400 404 |  | 
| 405 | 
            +
                LOOKUP_HELP = <<~HELP
         | 
| 406 | 
            +
                  #{colorize(:cyan, 'Name')}
         | 
| 407 | 
            +
                      lookup
         | 
| 408 | 
            +
             | 
| 409 | 
            +
                  #{colorize(:cyan, 'Usage')}
         | 
| 410 | 
            +
                      bolt lookup <key> {--targets TARGETS | --query QUERY | --rerun FILTER}
         | 
| 411 | 
            +
                        [options]
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                  #{colorize(:cyan, 'Description')}
         | 
| 414 | 
            +
                      Look up a value with Hiera.
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                  #{colorize(:cyan, 'Documentation')}
         | 
| 417 | 
            +
                      Learn more about using Hiera with Bolt at https://pup.pt/bolt-hiera.
         | 
| 418 | 
            +
             | 
| 419 | 
            +
                  #{colorize(:cyan, 'Examples')}
         | 
| 420 | 
            +
                      bolt lookup password --targets servers
         | 
| 421 | 
            +
                HELP
         | 
| 422 | 
            +
             | 
| 401 423 | 
             
                MODULE_HELP = <<~HELP
         | 
| 402 424 | 
             
                  #{colorize(:cyan, 'Name')}
         | 
| 403 425 | 
             
                      module
         | 
    
        data/lib/bolt/catalog.rb
    CHANGED
    
    | @@ -65,7 +65,8 @@ module Bolt | |
| 65 65 | 
             
                  puppet_overrides = {
         | 
| 66 66 | 
             
                    bolt_pdb_client: pdb_client,
         | 
| 67 67 | 
             
                    bolt_inventory: inv,
         | 
| 68 | 
            -
                    bolt_project: bolt_project
         | 
| 68 | 
            +
                    bolt_project: bolt_project,
         | 
| 69 | 
            +
                    future: request['future']
         | 
| 69 70 | 
             
                  }
         | 
| 70 71 |  | 
| 71 72 | 
             
                  # Facts will be set by the catalog compiler, so we need to ensure
         | 
    
        data/lib/bolt/cli.rb
    CHANGED
    
    | @@ -33,18 +33,19 @@ module Bolt | |
| 33 33 |  | 
| 34 34 | 
             
              class CLI
         | 
| 35 35 | 
             
                COMMANDS = {
         | 
| 36 | 
            -
                  ' | 
| 37 | 
            -
                  ' | 
| 38 | 
            -
                  ' | 
| 39 | 
            -
                  ' | 
| 40 | 
            -
                  ' | 
| 41 | 
            -
                  'secret' => %w[encrypt decrypt createkeys],
         | 
| 36 | 
            +
                  'apply'     => %w[],
         | 
| 37 | 
            +
                  'command'   => %w[run],
         | 
| 38 | 
            +
                  'file'      => %w[download upload],
         | 
| 39 | 
            +
                  'group'     => %w[show],
         | 
| 40 | 
            +
                  'guide'     => %w[],
         | 
| 42 41 | 
             
                  'inventory' => %w[show],
         | 
| 43 | 
            -
                  ' | 
| 44 | 
            -
                  ' | 
| 45 | 
            -
                  ' | 
| 46 | 
            -
                  ' | 
| 47 | 
            -
                  ' | 
| 42 | 
            +
                  'lookup'    => %w[],
         | 
| 43 | 
            +
                  'module'    => %w[add generate-types install show],
         | 
| 44 | 
            +
                  'plan'      => %w[show run convert new],
         | 
| 45 | 
            +
                  'project'   => %w[init migrate],
         | 
| 46 | 
            +
                  'script'    => %w[run],
         | 
| 47 | 
            +
                  'secret'    => %w[encrypt decrypt createkeys],
         | 
| 48 | 
            +
                  'task'      => %w[show run]
         | 
| 48 49 | 
             
                }.freeze
         | 
| 49 50 |  | 
| 50 51 | 
             
                TARGETING_OPTIONS = %i[query rerun targets].freeze
         | 
| @@ -326,6 +327,10 @@ module Bolt | |
| 326 327 | 
             
                    raise Bolt::CLIError, "a manifest file or --execute is required"
         | 
| 327 328 | 
             
                  end
         | 
| 328 329 |  | 
| 330 | 
            +
                  if options[:subcommand] == 'lookup' && !options[:object]
         | 
| 331 | 
            +
                    raise Bolt::CLIError, "Must specify a key to look up"
         | 
| 332 | 
            +
                  end
         | 
| 333 | 
            +
             | 
| 329 334 | 
             
                  if options[:subcommand] == 'command' && (!options[:object] || options[:object].empty?)
         | 
| 330 335 | 
             
                    raise Bolt::CLIError, "Must specify a command to run"
         | 
| 331 336 | 
             
                  end
         | 
| @@ -511,6 +516,8 @@ module Bolt | |
| 511 516 | 
             
                    when 'migrate'
         | 
| 512 517 | 
             
                      code = Bolt::ProjectManager.new(config, outputter, pal).migrate
         | 
| 513 518 | 
             
                    end
         | 
| 519 | 
            +
                  when 'lookup'
         | 
| 520 | 
            +
                    code = lookup(options[:object], options[:targets])
         | 
| 514 521 | 
             
                  when 'plan'
         | 
| 515 522 | 
             
                    case options[:action]
         | 
| 516 523 | 
             
                    when 'new'
         | 
| @@ -563,7 +570,8 @@ module Bolt | |
| 563 570 | 
             
                        when 'command'
         | 
| 564 571 | 
             
                          executor.run_command(targets, options[:object], executor_opts)
         | 
| 565 572 | 
             
                        when 'script'
         | 
| 566 | 
            -
                          script_path = find_file(options[:object])
         | 
| 573 | 
            +
                          script_path = find_file(options[:object], executor.future&.fetch('file_paths', false))
         | 
| 574 | 
            +
                          validate_file('script', script_path)
         | 
| 567 575 | 
             
                          executor.run_script(targets, script_path, options[:leftovers], executor_opts)
         | 
| 568 576 | 
             
                        when 'task'
         | 
| 569 577 | 
             
                          pal.run_task(options[:object],
         | 
| @@ -588,8 +596,9 @@ module Bolt | |
| 588 596 | 
             
                            dest = File.expand_path(dest, Dir.pwd)
         | 
| 589 597 | 
             
                            executor.download_file(targets, src, dest, executor_opts)
         | 
| 590 598 | 
             
                          when 'upload'
         | 
| 591 | 
            -
                             | 
| 592 | 
            -
                             | 
| 599 | 
            +
                            src_path = find_file(src, executor.future&.fetch('file_paths', false))
         | 
| 600 | 
            +
                            validate_file('source file', src_path, true)
         | 
| 601 | 
            +
                            executor.upload_file(targets, src_path, dest, executor_opts)
         | 
| 593 602 | 
             
                          end
         | 
| 594 603 | 
             
                        end
         | 
| 595 604 | 
             
                    end
         | 
| @@ -686,6 +695,38 @@ module Bolt | |
| 686 695 | 
             
                  outputter.print_groups(inventory.group_names.sort, inventory.source, config.default_inventoryfile)
         | 
| 687 696 | 
             
                end
         | 
| 688 697 |  | 
| 698 | 
            +
                # Looks up a value with Hiera, using targets as the contexts to perform the
         | 
| 699 | 
            +
                # look ups in.
         | 
| 700 | 
            +
                #
         | 
| 701 | 
            +
                def lookup(key, targets)
         | 
| 702 | 
            +
                  executor = Bolt::Executor.new(
         | 
| 703 | 
            +
                    config.concurrency,
         | 
| 704 | 
            +
                    analytics,
         | 
| 705 | 
            +
                    options[:noop],
         | 
| 706 | 
            +
                    config.modified_concurrency,
         | 
| 707 | 
            +
                    config.future
         | 
| 708 | 
            +
                  )
         | 
| 709 | 
            +
             | 
| 710 | 
            +
                  executor.subscribe(outputter) if options.fetch(:format, 'human') == 'human'
         | 
| 711 | 
            +
                  executor.subscribe(log_outputter)
         | 
| 712 | 
            +
                  executor.publish_event(type: :plan_start, plan: nil)
         | 
| 713 | 
            +
             | 
| 714 | 
            +
                  results = outputter.spin do
         | 
| 715 | 
            +
                    pal.lookup(
         | 
| 716 | 
            +
                      key,
         | 
| 717 | 
            +
                      targets,
         | 
| 718 | 
            +
                      inventory,
         | 
| 719 | 
            +
                      executor,
         | 
| 720 | 
            +
                      config.concurrency
         | 
| 721 | 
            +
                    )
         | 
| 722 | 
            +
                  end
         | 
| 723 | 
            +
             | 
| 724 | 
            +
                  executor.shutdown
         | 
| 725 | 
            +
                  outputter.print_result_set(results)
         | 
| 726 | 
            +
             | 
| 727 | 
            +
                  results.ok ? 0 : 1
         | 
| 728 | 
            +
                end
         | 
| 729 | 
            +
             | 
| 689 730 | 
             
                def run_plan(plan_name, plan_arguments, nodes, options)
         | 
| 690 731 | 
             
                  unless nodes.empty?
         | 
| 691 732 | 
             
                    if plan_arguments['nodes'] || plan_arguments['targets']
         | 
| @@ -929,20 +970,17 @@ module Bolt | |
| 929 970 | 
             
                # the path is a Puppet file path and looks for the file in a module's files
         | 
| 930 971 | 
             
                # directory.
         | 
| 931 972 | 
             
                #
         | 
| 932 | 
            -
                def find_file(path)
         | 
| 933 | 
            -
                   | 
| 934 | 
            -
             | 
| 935 | 
            -
             | 
| 936 | 
            -
             | 
| 937 | 
            -
             | 
| 938 | 
            -
             | 
| 939 | 
            -
             | 
| 940 | 
            -
             | 
| 941 | 
            -
                     | 
| 973 | 
            +
                def find_file(path, future_file_paths)
         | 
| 974 | 
            +
                  return path if File.exist?(path) || Pathname.new(path).absolute?
         | 
| 975 | 
            +
                  modulepath = Bolt::Config::Modulepath.new(config.modulepath)
         | 
| 976 | 
            +
                  modules    = Bolt::Module.discover(modulepath.full_modulepath, config.project)
         | 
| 977 | 
            +
                  mod, file = path.split(File::SEPARATOR, 2)
         | 
| 978 | 
            +
             | 
| 979 | 
            +
                  if modules[mod]
         | 
| 980 | 
            +
                    @logger.debug("Did not find file at #{File.expand_path(path)}, checking in module '#{mod}'")
         | 
| 981 | 
            +
                    found = Bolt::Util.find_file_in_module(modules[mod].path, file || "", future_file_paths)
         | 
| 982 | 
            +
                    path = found.nil? ? File.join(modules[mod].path, 'files', file) : found
         | 
| 942 983 | 
             
                  end
         | 
| 943 | 
            -
             | 
| 944 | 
            -
                  Bolt::Util.validate_file('script', path)
         | 
| 945 | 
            -
             | 
| 946 984 | 
             
                  path
         | 
| 947 985 | 
             
                end
         | 
| 948 986 |  | 
    
        data/lib/bolt/outputter/human.rb
    CHANGED
    
    | @@ -174,12 +174,16 @@ module Bolt | |
| 174 174 | 
             
                        @stream.puts(remove_trail(indent(2, result.message)))
         | 
| 175 175 | 
             
                      end
         | 
| 176 176 |  | 
| 177 | 
            -
                       | 
| 178 | 
            -
                       | 
| 177 | 
            +
                      case result.action
         | 
| 178 | 
            +
                      when 'command', 'script'
         | 
| 179 179 | 
             
                        safe_value = result.safe_value
         | 
| 180 180 | 
             
                        @stream.puts(indent(2, safe_value['merged_output'])) unless safe_value['merged_output'].strip.empty?
         | 
| 181 | 
            -
                       | 
| 182 | 
            -
                        @stream.puts(indent(2,  | 
| 181 | 
            +
                      when 'lookup'
         | 
| 182 | 
            +
                        @stream.puts(indent(2, result['value']))
         | 
| 183 | 
            +
                      else
         | 
| 184 | 
            +
                        if result.generic_value.any?
         | 
| 185 | 
            +
                          @stream.puts(indent(2, ::JSON.pretty_generate(result.generic_value)))
         | 
| 186 | 
            +
                        end
         | 
| 183 187 | 
             
                      end
         | 
| 184 188 | 
             
                    end
         | 
| 185 189 | 
             
                  end
         | 
    
        data/lib/bolt/outputter/json.rb
    CHANGED
    
    
    
        data/lib/bolt/pal.rb
    CHANGED
    
    | @@ -615,5 +615,50 @@ module Bolt | |
| 615 615 | 
             
                rescue Bolt::Error => e
         | 
| 616 616 | 
             
                  Bolt::PlanResult.new(e, 'failure')
         | 
| 617 617 | 
             
                end
         | 
| 618 | 
            +
             | 
| 619 | 
            +
                def lookup(key, targets, inventory, executor, _concurrency)
         | 
| 620 | 
            +
                  # Install the puppet-agent package and collect facts. Facts are
         | 
| 621 | 
            +
                  # automatically added to the targets.
         | 
| 622 | 
            +
                  in_plan_compiler(executor, inventory, nil) do |compiler|
         | 
| 623 | 
            +
                    compiler.call_function('apply_prep', targets)
         | 
| 624 | 
            +
                  end
         | 
| 625 | 
            +
             | 
| 626 | 
            +
                  overrides = {
         | 
| 627 | 
            +
                    bolt_inventory: inventory,
         | 
| 628 | 
            +
                    bolt_project:   @project
         | 
| 629 | 
            +
                  }
         | 
| 630 | 
            +
             | 
| 631 | 
            +
                  # Do a lookup with a catalog compiler, which uses the 'hierarchy' key in
         | 
| 632 | 
            +
                  # Hiera config.
         | 
| 633 | 
            +
                  results = targets.map do |target|
         | 
| 634 | 
            +
                    node = Puppet::Node.from_data_hash(
         | 
| 635 | 
            +
                      'name'       => target.name,
         | 
| 636 | 
            +
                      'parameters' => { 'clientcert' => target.name }
         | 
| 637 | 
            +
                    )
         | 
| 638 | 
            +
             | 
| 639 | 
            +
                    trusted = Puppet::Context::TrustedInformation.local(node).to_h
         | 
| 640 | 
            +
             | 
| 641 | 
            +
                    env_conf = {
         | 
| 642 | 
            +
                      modulepath: @modulepath.full_modulepath,
         | 
| 643 | 
            +
                      facts:      target.facts,
         | 
| 644 | 
            +
                      variables:  target.vars
         | 
| 645 | 
            +
                    }
         | 
| 646 | 
            +
             | 
| 647 | 
            +
                    with_puppet_settings do
         | 
| 648 | 
            +
                      Puppet::Pal.in_tmp_environment(target.name, **env_conf) do |pal|
         | 
| 649 | 
            +
                        Puppet.override(overrides) do
         | 
| 650 | 
            +
                          Puppet.lookup(:pal_current_node).trusted_data = trusted
         | 
| 651 | 
            +
                          pal.with_catalog_compiler do |compiler|
         | 
| 652 | 
            +
                            Bolt::Result.for_lookup(target, key, compiler.call_function('lookup', key))
         | 
| 653 | 
            +
                          rescue StandardError => e
         | 
| 654 | 
            +
                            Bolt::Result.from_exception(target, e)
         | 
| 655 | 
            +
                          end
         | 
| 656 | 
            +
                        end
         | 
| 657 | 
            +
                      end
         | 
| 658 | 
            +
                    end
         | 
| 659 | 
            +
                  end
         | 
| 660 | 
            +
             | 
| 661 | 
            +
                  Bolt::ResultSet.new(results)
         | 
| 662 | 
            +
                end
         | 
| 618 663 | 
             
              end
         | 
| 619 664 | 
             
            end
         | 
    
        data/lib/bolt/result.rb
    CHANGED
    
    | @@ -28,6 +28,11 @@ module Bolt | |
| 28 28 | 
             
                  %w[file line].zip(position).to_h.compact
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 | 
            +
                def self.for_lookup(target, key, value)
         | 
| 32 | 
            +
                  val = { 'value' => value }
         | 
| 33 | 
            +
                  new(target, value: val, action: 'lookup', object: key)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 31 36 | 
             
                def self.for_command(target, value, action, command, position)
         | 
| 32 37 | 
             
                  details = create_details(position)
         | 
| 33 38 | 
             
                  unless value['exit_code'] == 0
         | 
    
        data/lib/bolt/util.rb
    CHANGED
    
    | @@ -85,6 +85,66 @@ module Bolt | |
| 85 85 | 
             
                    Bolt::Config.user_path && !File.exist?(first_runs_free)
         | 
| 86 86 | 
             
                  end
         | 
| 87 87 |  | 
| 88 | 
            +
                  # If Puppet is loaded, we aleady have the path to the module and should
         | 
| 89 | 
            +
                  # just get it. This takes the path to a file provided by the user and a
         | 
| 90 | 
            +
                  # Puppet Parser scope object and tries to find the file, either as an
         | 
| 91 | 
            +
                  # absolute path or Puppet module syntax lookup. Returns the path to the
         | 
| 92 | 
            +
                  # file if found, or nil.
         | 
| 93 | 
            +
                  #
         | 
| 94 | 
            +
                  def find_file_from_scope(file, scope, fallback = false)
         | 
| 95 | 
            +
                    # If we got an absolute path, just return that.
         | 
| 96 | 
            +
                    return file if Pathname.new(file).absolute?
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    module_name, file_pattern = Bolt::Util.split_path(file)
         | 
| 99 | 
            +
                    # Get the absolute path to the module root from the scope
         | 
| 100 | 
            +
                    mod_path = scope.compiler.environment.module(module_name)&.path
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    # Search the module for the file, falling back to new-style paths if enabled.
         | 
| 103 | 
            +
                    find_file_in_module(mod_path, file_pattern, fallback) if mod_path
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  # This method is used by Bolt to find files when provided a
         | 
| 107 | 
            +
                  # module-style path without loading Puppet. It takes the absolute path to
         | 
| 108 | 
            +
                  # the module root and the module-style path minus the module name and
         | 
| 109 | 
            +
                  # searches subdirectories in the module in order of precedence.
         | 
| 110 | 
            +
                  #
         | 
| 111 | 
            +
                  def find_file_in_module(module_path, module_file, fallback = false)
         | 
| 112 | 
            +
                    # If the first part of the path is 'scripts' or 'files', the path may
         | 
| 113 | 
            +
                    # be a new-style file location and should fall back to the new path.
         | 
| 114 | 
            +
                    subdir_or_file = split_path(module_file).first
         | 
| 115 | 
            +
                    case subdir_or_file
         | 
| 116 | 
            +
                      # For any subdirs that may indicate the user passed a new-style path,
         | 
| 117 | 
            +
                      # first look in 'mymod/files/<relative_path>' (old-style) then fall
         | 
| 118 | 
            +
                      # back to 'mymod/<relative_path>' (new-style) if enabled.
         | 
| 119 | 
            +
                    when 'scripts', 'files'
         | 
| 120 | 
            +
                      search_module(module_path, module_file, fallback)
         | 
| 121 | 
            +
                    else
         | 
| 122 | 
            +
                      # If the path definitely isn't new-style, only look in the 'files/'
         | 
| 123 | 
            +
                      # directory.
         | 
| 124 | 
            +
                      search_module(module_path, module_file)
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  # This searches a module for files under 'files/' or 'scripts/',
         | 
| 129 | 
            +
                  # optionally falling back to the new style of file loading. It takes the
         | 
| 130 | 
            +
                  # absolute path to the module root, the relative path provided by the
         | 
| 131 | 
            +
                  # user, and whether to fall back to the new-style script loading if the
         | 
| 132 | 
            +
                  # file isn't found in 'files/'.
         | 
| 133 | 
            +
                  #
         | 
| 134 | 
            +
                  private def search_module(module_path, module_file, fallback = false)
         | 
| 135 | 
            +
                    if File.exist?(File.join(module_path, 'files', module_file))
         | 
| 136 | 
            +
                      File.join(module_path, 'files', module_file)
         | 
| 137 | 
            +
                    elsif File.exist?(File.join(module_path, module_file)) && fallback
         | 
| 138 | 
            +
                      File.join(module_path, module_file)
         | 
| 139 | 
            +
                    end
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  # Copied directly from puppet/lib/puppet/parser/files.rb
         | 
| 143 | 
            +
                  #
         | 
| 144 | 
            +
                  def split_path(path)
         | 
| 145 | 
            +
                    path.split(File::SEPARATOR, 2)
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 88 148 | 
             
                  # Accepts a path with either 'plans' or 'tasks' in it and determines
         | 
| 89 149 | 
             
                  # the name of the module
         | 
| 90 150 | 
             
                  def module_name(path)
         | 
    
        data/lib/bolt/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: bolt
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.8.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Puppet
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-05-03 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: addressable
         |