bolt 3.3.0 → 3.7.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 +5 -5
 - data/bolt-modules/boltlib/lib/puppet/datatypes/containerresult.rb +24 -0
 - data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_command.rb +66 -0
 - data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +20 -2
 - data/bolt-modules/boltlib/lib/puppet/functions/run_container.rb +162 -0
 - data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +19 -2
 - data/bolt-modules/boltlib/types/planresult.pp +1 -0
 - data/bolt-modules/prompt/lib/puppet/functions/prompt.rb +20 -2
 - data/bolt-modules/prompt/lib/puppet/functions/prompt/menu.rb +103 -0
 - data/guides/targets.txt +31 -0
 - data/lib/bolt/analytics.rb +4 -8
 - data/lib/bolt/bolt_option_parser.rb +35 -17
 - data/lib/bolt/cli.rb +109 -28
 - data/lib/bolt/config.rb +11 -7
 - data/lib/bolt/config/options.rb +41 -9
 - data/lib/bolt/config/transport/lxd.rb +3 -1
 - data/lib/bolt/config/transport/options.rb +7 -0
 - data/lib/bolt/config/transport/podman.rb +33 -0
 - data/lib/bolt/container_result.rb +105 -0
 - data/lib/bolt/error.rb +15 -0
 - data/lib/bolt/executor.rb +27 -15
 - data/lib/bolt/inventory.rb +5 -4
 - data/lib/bolt/inventory/inventory.rb +3 -2
 - data/lib/bolt/inventory/options.rb +9 -0
 - data/lib/bolt/inventory/target.rb +16 -0
 - data/lib/bolt/node/output.rb +14 -4
 - data/lib/bolt/outputter/human.rb +243 -84
 - data/lib/bolt/outputter/json.rb +6 -4
 - data/lib/bolt/outputter/logger.rb +17 -0
 - data/lib/bolt/pal.rb +22 -2
 - data/lib/bolt/pal/yaml_plan/step.rb +4 -2
 - data/lib/bolt/pal/yaml_plan/step/command.rb +8 -0
 - data/lib/bolt/pal/yaml_plan/step/script.rb +4 -0
 - data/lib/bolt/pal/yaml_plan/transpiler.rb +2 -2
 - data/lib/bolt/plan_creator.rb +2 -2
 - data/lib/bolt/plugin.rb +13 -11
 - data/lib/bolt/puppetdb/client.rb +54 -0
 - data/lib/bolt/result.rb +5 -14
 - data/lib/bolt/shell/bash.rb +33 -22
 - data/lib/bolt/shell/powershell.rb +6 -8
 - data/lib/bolt/transport/docker.rb +1 -1
 - data/lib/bolt/transport/docker/connection.rb +21 -32
 - data/lib/bolt/transport/lxd/connection.rb +5 -5
 - data/lib/bolt/transport/orch.rb +13 -5
 - data/lib/bolt/transport/podman.rb +19 -0
 - data/lib/bolt/transport/podman/connection.rb +98 -0
 - data/lib/bolt/util.rb +42 -0
 - data/lib/bolt/version.rb +1 -1
 - data/lib/bolt_server/transport_app.rb +3 -0
 - data/lib/bolt_spec/plans/action_stubs/command_stub.rb +8 -1
 - data/lib/bolt_spec/plans/action_stubs/script_stub.rb +8 -1
 - data/lib/bolt_spec/plans/mock_executor.rb +91 -11
 - data/modules/puppet_connect/plans/test_input_data.pp +22 -0
 - metadata +11 -2
 
    
        data/lib/bolt/inventory.rb
    CHANGED
    
    | 
         @@ -86,6 +86,7 @@ module Bolt 
     | 
|
| 
       86 
86 
     | 
    
         
             
                    if config.default_inventoryfile.exist?
         
     | 
| 
       87 
87 
     | 
    
         
             
                      logger.debug("Loaded inventory from #{config.default_inventoryfile}")
         
     | 
| 
       88 
88 
     | 
    
         
             
                    else
         
     | 
| 
      
 89 
     | 
    
         
            +
                      source = nil
         
     | 
| 
       89 
90 
     | 
    
         
             
                      logger.debug("Tried to load inventory from #{config.default_inventoryfile}, but the file does not exist")
         
     | 
| 
       90 
91 
     | 
    
         
             
                    end
         
     | 
| 
       91 
92 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -100,17 +101,17 @@ module Bolt 
     | 
|
| 
       100 
101 
     | 
    
         
             
                    validator.warnings.each { |warning| Bolt::Logger.warn(warning[:id], warning[:msg]) }
         
     | 
| 
       101 
102 
     | 
    
         
             
                  end
         
     | 
| 
       102 
103 
     | 
    
         | 
| 
       103 
     | 
    
         
            -
                  inventory = create_version(data, config.transport, config.transports, plugins)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  inventory = create_version(data, config.transport, config.transports, plugins, source)
         
     | 
| 
       104 
105 
     | 
    
         
             
                  inventory.validate
         
     | 
| 
       105 
106 
     | 
    
         
             
                  inventory
         
     | 
| 
       106 
107 
     | 
    
         
             
                end
         
     | 
| 
       107 
108 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                def self.create_version(data, transport, transports, plugins)
         
     | 
| 
      
 109 
     | 
    
         
            +
                def self.create_version(data, transport, transports, plugins, source = nil)
         
     | 
| 
       109 
110 
     | 
    
         
             
                  version = (data || {}).delete('version') { 2 }
         
     | 
| 
       110 
111 
     | 
    
         | 
| 
       111 
112 
     | 
    
         
             
                  case version
         
     | 
| 
       112 
113 
     | 
    
         
             
                  when 2
         
     | 
| 
       113 
     | 
    
         
            -
                    Bolt::Inventory::Inventory.new(data, transport, transports, plugins)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    Bolt::Inventory::Inventory.new(data, transport, transports, plugins, source)
         
     | 
| 
       114 
115 
     | 
    
         
             
                  else
         
     | 
| 
       115 
116 
     | 
    
         
             
                    raise ValidationError.new("Unsupported version #{version} specified in inventory", nil)
         
     | 
| 
       116 
117 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -120,7 +121,7 @@ module Bolt 
     | 
|
| 
       120 
121 
     | 
    
         
             
                  config  = Bolt::Config.default
         
     | 
| 
       121 
122 
     | 
    
         
             
                  plugins = Bolt::Plugin.setup(config, nil)
         
     | 
| 
       122 
123 
     | 
    
         | 
| 
       123 
     | 
    
         
            -
                  create_version({}, config.transport, config.transports, plugins)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  create_version({}, config.transport, config.transports, plugins, nil)
         
     | 
| 
       124 
125 
     | 
    
         
             
                end
         
     | 
| 
       125 
126 
     | 
    
         
             
              end
         
     | 
| 
       126 
127 
     | 
    
         
             
            end
         
     | 
| 
         @@ -6,7 +6,7 @@ require 'bolt/inventory/target' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            module Bolt
         
     | 
| 
       7 
7 
     | 
    
         
             
              class Inventory
         
     | 
| 
       8 
8 
     | 
    
         
             
                class Inventory
         
     | 
| 
       9 
     | 
    
         
            -
                  attr_reader : 
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :config, :plugins, :source, :targets, :transport
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                  class WildcardError < Bolt::Error
         
     | 
| 
       12 
12 
     | 
    
         
             
                    def initialize(target)
         
     | 
| 
         @@ -15,7 +15,7 @@ module Bolt 
     | 
|
| 
       15 
15 
     | 
    
         
             
                  end
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
                  # TODO: Pass transport config instead of config object
         
     | 
| 
       18 
     | 
    
         
            -
                  def initialize(data, transport, transports, plugins)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def initialize(data, transport, transports, plugins, source = nil)
         
     | 
| 
       19 
19 
     | 
    
         
             
                    @logger       = Bolt::Logger.logger(self)
         
     | 
| 
       20 
20 
     | 
    
         
             
                    @data         = data || {}
         
     | 
| 
       21 
21 
     | 
    
         
             
                    @transport    = transport
         
     | 
| 
         @@ -24,6 +24,7 @@ module Bolt 
     | 
|
| 
       24 
24 
     | 
    
         
             
                    @groups       = Group.new(@data, plugins, all_group: true)
         
     | 
| 
       25 
25 
     | 
    
         
             
                    @group_lookup = {}
         
     | 
| 
       26 
26 
     | 
    
         
             
                    @targets      = {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @source       = source
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
       28 
29 
     | 
    
         
             
                    @groups.resolve_string_targets(@groups.target_aliases, @groups.all_targets)
         
     | 
| 
       29 
30 
     | 
    
         | 
| 
         @@ -11,8 +11,10 @@ module Bolt 
     | 
|
| 
       11 
11 
     | 
    
         
             
                    facts
         
     | 
| 
       12 
12 
     | 
    
         
             
                    features
         
     | 
| 
       13 
13 
     | 
    
         
             
                    groups
         
     | 
| 
      
 14 
     | 
    
         
            +
                    plugin_hooks
         
     | 
| 
       14 
15 
     | 
    
         
             
                    targets
         
     | 
| 
       15 
16 
     | 
    
         
             
                    vars
         
     | 
| 
      
 17 
     | 
    
         
            +
                    version
         
     | 
| 
       16 
18 
     | 
    
         
             
                  ].freeze
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
20 
     | 
    
         
             
                  # Definitions used to validate the data.
         
     | 
| 
         @@ -123,6 +125,13 @@ module Bolt 
     | 
|
| 
       123 
125 
     | 
    
         
             
                      description: "A map of variables for the group or target.",
         
     | 
| 
       124 
126 
     | 
    
         
             
                      type: Hash,
         
     | 
| 
       125 
127 
     | 
    
         
             
                      _plugin: true
         
     | 
| 
      
 128 
     | 
    
         
            +
                    },
         
     | 
| 
      
 129 
     | 
    
         
            +
                    "version" => {
         
     | 
| 
      
 130 
     | 
    
         
            +
                      description: "The version of the inventory file.",
         
     | 
| 
      
 131 
     | 
    
         
            +
                      type: Integer,
         
     | 
| 
      
 132 
     | 
    
         
            +
                      _plugin: false,
         
     | 
| 
      
 133 
     | 
    
         
            +
                      _example: 2,
         
     | 
| 
      
 134 
     | 
    
         
            +
                      _default: 2
         
     | 
| 
       126 
135 
     | 
    
         
             
                    }
         
     | 
| 
       127 
136 
     | 
    
         
             
                  }.freeze
         
     | 
| 
       128 
137 
     | 
    
         
             
                end
         
     | 
| 
         @@ -92,6 +92,7 @@ module Bolt 
     | 
|
| 
       92 
92 
     | 
    
         
             
                  end
         
     | 
| 
       93 
93 
     | 
    
         | 
| 
       94 
94 
     | 
    
         
             
                  def add_facts(new_facts = {})
         
     | 
| 
      
 95 
     | 
    
         
            +
                    validate_fact_names(new_facts)
         
     | 
| 
       95 
96 
     | 
    
         
             
                    @facts = Bolt::Util.deep_merge(@facts, new_facts)
         
     | 
| 
       96 
97 
     | 
    
         
             
                  end
         
     | 
| 
       97 
98 
     | 
    
         | 
| 
         @@ -153,9 +154,24 @@ module Bolt 
     | 
|
| 
       153 
154 
     | 
    
         
             
                      raise Bolt::UnknownTransportError.new(transport, uri)
         
     | 
| 
       154 
155 
     | 
    
         
             
                    end
         
     | 
| 
       155 
156 
     | 
    
         | 
| 
      
 157 
     | 
    
         
            +
                    validate_fact_names(facts)
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
       156 
159 
     | 
    
         
             
                    transport_config
         
     | 
| 
       157 
160 
     | 
    
         
             
                  end
         
     | 
| 
       158 
161 
     | 
    
         | 
| 
      
 162 
     | 
    
         
            +
                  # Validate fact names and issue a deprecation warning if any fact names have a dot.
         
     | 
| 
      
 163 
     | 
    
         
            +
                  #
         
     | 
| 
      
 164 
     | 
    
         
            +
                  private def validate_fact_names(facts)
         
     | 
| 
      
 165 
     | 
    
         
            +
                    if (dotted = facts.keys.select { |name| name.include?('.') }).any?
         
     | 
| 
      
 166 
     | 
    
         
            +
                      Bolt::Logger.deprecate(
         
     | 
| 
      
 167 
     | 
    
         
            +
                        'dotted_fact_name',
         
     | 
| 
      
 168 
     | 
    
         
            +
                        "Target '#{safe_name}' includes dotted fact names: '#{dotted.join("', '")}'. Dotted fact "\
         
     | 
| 
      
 169 
     | 
    
         
            +
                        "names are deprecated and Bolt does not automatically convert facts with dotted names to "\
         
     | 
| 
      
 170 
     | 
    
         
            +
                        "structured facts. For more information, see https://pup.pt/bolt-dotted-facts"
         
     | 
| 
      
 171 
     | 
    
         
            +
                      )
         
     | 
| 
      
 172 
     | 
    
         
            +
                    end
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
       159 
175 
     | 
    
         
             
                  def host
         
     | 
| 
       160 
176 
     | 
    
         
             
                    @uri_obj.hostname || transport_config['host']
         
     | 
| 
       161 
177 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/bolt/node/output.rb
    CHANGED
    
    | 
         @@ -6,13 +6,23 @@ require 'bolt/result' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            module Bolt
         
     | 
| 
       7 
7 
     | 
    
         
             
              class Node
         
     | 
| 
       8 
8 
     | 
    
         
             
                class Output
         
     | 
| 
       9 
     | 
    
         
            -
                  attr_reader :stdout, : 
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :stderr, :stdout, :merged_output
         
     | 
| 
       10 
10 
     | 
    
         
             
                  attr_accessor :exit_code
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  def initialize
         
     | 
| 
       13 
     | 
    
         
            -
                    @stdout 
     | 
| 
       14 
     | 
    
         
            -
                    @stderr 
     | 
| 
       15 
     | 
    
         
            -
                    @ 
     | 
| 
      
 13 
     | 
    
         
            +
                    @stdout        = StringIO.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @stderr        = StringIO.new
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @merged_output = StringIO.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @exit_code     = 'unknown'
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 20 
     | 
    
         
            +
                    {
         
     | 
| 
      
 21 
     | 
    
         
            +
                      'stdout'        => @stdout.string,
         
     | 
| 
      
 22 
     | 
    
         
            +
                      'stderr'        => @stderr.string,
         
     | 
| 
      
 23 
     | 
    
         
            +
                      'merged_output' => @merged_output.string,
         
     | 
| 
      
 24 
     | 
    
         
            +
                      'exit_code'     => @exit_code
         
     | 
| 
      
 25 
     | 
    
         
            +
                    }
         
     | 
| 
       16 
26 
     | 
    
         
             
                  end
         
     | 
| 
       17 
27 
     | 
    
         
             
                end
         
     | 
| 
       18 
28 
     | 
    
         
             
              end
         
     | 
    
        data/lib/bolt/outputter/human.rb
    CHANGED
    
    | 
         @@ -6,6 +6,7 @@ module Bolt 
     | 
|
| 
       6 
6 
     | 
    
         
             
              class Outputter
         
     | 
| 
       7 
7 
     | 
    
         
             
                class Human < Bolt::Outputter
         
     | 
| 
       8 
8 
     | 
    
         
             
                  COLORS = {
         
     | 
| 
      
 9 
     | 
    
         
            +
                    dim:    "2", # Dim, the other color of the rainbow
         
     | 
| 
       9 
10 
     | 
    
         
             
                    red:    "31",
         
     | 
| 
       10 
11 
     | 
    
         
             
                    green:  "32",
         
     | 
| 
       11 
12 
     | 
    
         
             
                    yellow: "33",
         
     | 
| 
         @@ -92,6 +93,10 @@ module Bolt 
     | 
|
| 
       92 
93 
     | 
    
         
             
                        print_plan_start(event)
         
     | 
| 
       93 
94 
     | 
    
         
             
                      when :plan_finish
         
     | 
| 
       94 
95 
     | 
    
         
             
                        print_plan_finish(event)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      when :container_start
         
     | 
| 
      
 97 
     | 
    
         
            +
                        print_container_start(event) if plan_logging?
         
     | 
| 
      
 98 
     | 
    
         
            +
                      when :container_finish
         
     | 
| 
      
 99 
     | 
    
         
            +
                        print_container_finish(event) if plan_logging?
         
     | 
| 
       95 
100 
     | 
    
         
             
                      when :start_spin
         
     | 
| 
       96 
101 
     | 
    
         
             
                        start_spin
         
     | 
| 
       97 
102 
     | 
    
         
             
                      when :stop_spin
         
     | 
| 
         @@ -112,6 +117,34 @@ module Bolt 
     | 
|
| 
       112 
117 
     | 
    
         
             
                    @stream.puts(colorize(:green, "Started on #{target.safe_name}..."))
         
     | 
| 
       113 
118 
     | 
    
         
             
                  end
         
     | 
| 
       114 
119 
     | 
    
         | 
| 
      
 120 
     | 
    
         
            +
                  def print_container_result(result)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    if result.success?
         
     | 
| 
      
 122 
     | 
    
         
            +
                      @stream.puts(colorize(:green, "Finished running container #{result.object}:"))
         
     | 
| 
      
 123 
     | 
    
         
            +
                    else
         
     | 
| 
      
 124 
     | 
    
         
            +
                      @stream.puts(colorize(:red, "Failed running container #{result.object}:"))
         
     | 
| 
      
 125 
     | 
    
         
            +
                    end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                    if result.error_hash
         
     | 
| 
      
 128 
     | 
    
         
            +
                      @stream.puts(colorize(:red, remove_trail(indent(2, result.error_hash['msg']))))
         
     | 
| 
      
 129 
     | 
    
         
            +
                      return 0
         
     | 
| 
      
 130 
     | 
    
         
            +
                    end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                    # Only print results if there's something other than empty string and hash
         
     | 
| 
      
 133 
     | 
    
         
            +
                    safe_value = result.safe_value
         
     | 
| 
      
 134 
     | 
    
         
            +
                    if safe_value['stdout'].strip.empty? && safe_value['stderr'].strip.empty?
         
     | 
| 
      
 135 
     | 
    
         
            +
                      @stream.puts(indent(2, "Running container #{result.object} completed successfully with no result"))
         
     | 
| 
      
 136 
     | 
    
         
            +
                    else
         
     | 
| 
      
 137 
     | 
    
         
            +
                      unless safe_value['stdout'].strip && safe_value['stdout'].strip.empty?
         
     | 
| 
      
 138 
     | 
    
         
            +
                        @stream.puts(indent(2, "STDOUT:"))
         
     | 
| 
      
 139 
     | 
    
         
            +
                        @stream.puts(indent(4, safe_value['stdout']))
         
     | 
| 
      
 140 
     | 
    
         
            +
                      end
         
     | 
| 
      
 141 
     | 
    
         
            +
                      unless safe_value['stderr'].strip.empty?
         
     | 
| 
      
 142 
     | 
    
         
            +
                        @stream.puts(indent(2, "STDERR:"))
         
     | 
| 
      
 143 
     | 
    
         
            +
                        @stream.puts(indent(4, safe_value['stderr']))
         
     | 
| 
      
 144 
     | 
    
         
            +
                      end
         
     | 
| 
      
 145 
     | 
    
         
            +
                    end
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
       115 
148 
     | 
    
         
             
                  def print_result(result)
         
     | 
| 
       116 
149 
     | 
    
         
             
                    if result.success?
         
     | 
| 
       117 
150 
     | 
    
         
             
                      @stream.puts(colorize(:green, "Finished on #{result.target.safe_name}:"))
         
     | 
| 
         @@ -142,16 +175,9 @@ module Bolt 
     | 
|
| 
       142 
175 
     | 
    
         
             
                      end
         
     | 
| 
       143 
176 
     | 
    
         | 
| 
       144 
177 
     | 
    
         
             
                      # Use special handling if the result looks like a command or script result
         
     | 
| 
       145 
     | 
    
         
            -
                      if result.generic_value.keys == %w[stdout stderr exit_code]
         
     | 
| 
      
 178 
     | 
    
         
            +
                      if result.generic_value.keys == %w[stdout stderr merged_output exit_code]
         
     | 
| 
       146 
179 
     | 
    
         
             
                        safe_value = result.safe_value
         
     | 
| 
       147 
     | 
    
         
            -
                        unless safe_value[' 
     | 
| 
       148 
     | 
    
         
            -
                          @stream.puts(indent(2, "STDOUT:"))
         
     | 
| 
       149 
     | 
    
         
            -
                          @stream.puts(indent(4, safe_value['stdout']))
         
     | 
| 
       150 
     | 
    
         
            -
                        end
         
     | 
| 
       151 
     | 
    
         
            -
                        unless safe_value['stderr'].strip.empty?
         
     | 
| 
       152 
     | 
    
         
            -
                          @stream.puts(indent(2, "STDERR:"))
         
     | 
| 
       153 
     | 
    
         
            -
                          @stream.puts(indent(4, safe_value['stderr']))
         
     | 
| 
       154 
     | 
    
         
            -
                        end
         
     | 
| 
      
 180 
     | 
    
         
            +
                        @stream.puts(indent(2, safe_value['merged_output'])) unless safe_value['merged_output'].strip.empty?
         
     | 
| 
       155 
181 
     | 
    
         
             
                      elsif result.generic_value.any?
         
     | 
| 
       156 
182 
     | 
    
         
             
                        @stream.puts(indent(2, ::JSON.pretty_generate(result.generic_value)))
         
     | 
| 
       157 
183 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -187,6 +213,25 @@ module Bolt 
     | 
|
| 
       187 
213 
     | 
    
         
             
                    @stream.puts(colorize(:green, message))
         
     | 
| 
       188 
214 
     | 
    
         
             
                  end
         
     | 
| 
       189 
215 
     | 
    
         | 
| 
      
 216 
     | 
    
         
            +
                  def print_container_start(image:, **_kwargs)
         
     | 
| 
      
 217 
     | 
    
         
            +
                    @stream.puts(colorize(:green, "Starting: run container '#{image}'"))
         
     | 
| 
      
 218 
     | 
    
         
            +
                  end
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
                  def print_container_finish(event)
         
     | 
| 
      
 221 
     | 
    
         
            +
                    result = if event[:result].is_a?(Bolt::ContainerFailure)
         
     | 
| 
      
 222 
     | 
    
         
            +
                               event[:result].result
         
     | 
| 
      
 223 
     | 
    
         
            +
                             else
         
     | 
| 
      
 224 
     | 
    
         
            +
                               event[:result]
         
     | 
| 
      
 225 
     | 
    
         
            +
                             end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                    if result.success?
         
     | 
| 
      
 228 
     | 
    
         
            +
                      @stream.puts(colorize(:green, "Finished: run container '#{result.object}' succeeded."))
         
     | 
| 
      
 229 
     | 
    
         
            +
                    else
         
     | 
| 
      
 230 
     | 
    
         
            +
                      @stream.puts(colorize(:red, "Finished: run container '#{result.object}' failed."))
         
     | 
| 
      
 231 
     | 
    
         
            +
                    end
         
     | 
| 
      
 232 
     | 
    
         
            +
                    print_container_result(result) if @verbose
         
     | 
| 
      
 233 
     | 
    
         
            +
                  end
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
       190 
235 
     | 
    
         
             
                  def print_plan_start(event)
         
     | 
| 
       191 
236 
     | 
    
         
             
                    @plan_depth += 1
         
     | 
| 
       192 
237 
     | 
    
         
             
                    # We use this event to both mark the start of a plan _and_ to enable
         
     | 
| 
         @@ -269,78 +314,115 @@ module Bolt 
     | 
|
| 
       269 
314 
     | 
    
         | 
| 
       270 
315 
     | 
    
         
             
                  # @param [Hash] task A hash representing the task
         
     | 
| 
       271 
316 
     | 
    
         
             
                  def print_task_info(task)
         
     | 
| 
       272 
     | 
    
         
            -
                     
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
                     
     | 
| 
       275 
     | 
    
         
            -
             
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
      
 317 
     | 
    
         
            +
                    params = (task.parameters || []).sort
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 320 
     | 
    
         
            +
             
     | 
| 
      
 321 
     | 
    
         
            +
                    # Add task name and description
         
     | 
| 
      
 322 
     | 
    
         
            +
                    info << colorize(:cyan, "#{task.name}\n")
         
     | 
| 
      
 323 
     | 
    
         
            +
                    info << if task.description
         
     | 
| 
      
 324 
     | 
    
         
            +
                              indent(2, task.description.chomp)
         
     | 
| 
       277 
325 
     | 
    
         
             
                            else
         
     | 
| 
       278 
     | 
    
         
            -
                               
     | 
| 
      
 326 
     | 
    
         
            +
                              indent(2, 'No description')
         
     | 
| 
       279 
327 
     | 
    
         
             
                            end
         
     | 
| 
       280 
     | 
    
         
            -
             
     | 
| 
       281 
     | 
    
         
            -
             
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
      
 328 
     | 
    
         
            +
                    info << "\n\n"
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
                    # Build usage string
         
     | 
| 
      
 331 
     | 
    
         
            +
                    usage = +''
         
     | 
| 
      
 332 
     | 
    
         
            +
                    usage << if Bolt::Util.powershell?
         
     | 
| 
      
 333 
     | 
    
         
            +
                               "Invoke-BoltTask -Name #{task.name} -Targets <targets>"
         
     | 
| 
      
 334 
     | 
    
         
            +
                             else
         
     | 
| 
      
 335 
     | 
    
         
            +
                               "bolt task run #{task.name} --targets <targets>"
         
     | 
| 
      
 336 
     | 
    
         
            +
                             end
         
     | 
| 
      
 337 
     | 
    
         
            +
                    usage << (Bolt::Util.powershell? ? ' [-Noop]' : ' [--noop]') if task.supports_noop
         
     | 
| 
      
 338 
     | 
    
         
            +
                    params.each do |name, data|
         
     | 
| 
      
 339 
     | 
    
         
            +
                      usage << if data['type']&.start_with?('Optional')
         
     | 
| 
      
 340 
     | 
    
         
            +
                                 " [#{name}=<value>]"
         
     | 
| 
       287 
341 
     | 
    
         
             
                               else
         
     | 
| 
       288 
     | 
    
         
            -
                                 " #{ 
     | 
| 
      
 342 
     | 
    
         
            +
                                 " #{name}=<value>"
         
     | 
| 
       289 
343 
     | 
    
         
             
                               end
         
     | 
| 
       290 
344 
     | 
    
         
             
                    end
         
     | 
| 
       291 
345 
     | 
    
         | 
| 
       292 
     | 
    
         
            -
                     
     | 
| 
       293 
     | 
    
         
            -
             
     | 
| 
      
 346 
     | 
    
         
            +
                    # Add usage
         
     | 
| 
      
 347 
     | 
    
         
            +
                    info << colorize(:cyan, "Usage\n")
         
     | 
| 
      
 348 
     | 
    
         
            +
                    info << indent(2, wrap(usage))
         
     | 
| 
      
 349 
     | 
    
         
            +
                    info << "\n"
         
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
                    # Add parameters, if any
         
     | 
| 
      
 352 
     | 
    
         
            +
                    if params.any?
         
     | 
| 
      
 353 
     | 
    
         
            +
                      info << colorize(:cyan, "Parameters\n")
         
     | 
| 
      
 354 
     | 
    
         
            +
                      params.each do |name, data|
         
     | 
| 
      
 355 
     | 
    
         
            +
                        info << indent(2, "#{colorize(:yellow, name)}  #{colorize(:dim, data['type'] || 'Any')}\n")
         
     | 
| 
      
 356 
     | 
    
         
            +
                        info << indent(4, "#{wrap(data['description']).chomp}\n") if data['description']
         
     | 
| 
      
 357 
     | 
    
         
            +
                        info << indent(4, "Default: #{data['default'].inspect}\n") if data.key?('default')
         
     | 
| 
      
 358 
     | 
    
         
            +
                        info << "\n"
         
     | 
| 
      
 359 
     | 
    
         
            +
                      end
         
     | 
| 
       294 
360 
     | 
    
         
             
                    end
         
     | 
| 
       295 
361 
     | 
    
         | 
| 
       296 
     | 
    
         
            -
                     
     | 
| 
       297 
     | 
    
         
            -
                    task_info << " - #{task.description}" if task.description
         
     | 
| 
       298 
     | 
    
         
            -
                    task_info << "\n\n"
         
     | 
| 
       299 
     | 
    
         
            -
                    task_info << "USAGE:\n#{usage}\n\n"
         
     | 
| 
       300 
     | 
    
         
            -
                    task_info << "PARAMETERS:\n#{pretty_params}\n" unless pretty_params.empty?
         
     | 
| 
       301 
     | 
    
         
            -
                    task_info << "MODULE:\n"
         
     | 
| 
       302 
     | 
    
         
            -
             
     | 
| 
      
 362 
     | 
    
         
            +
                    # Add module location
         
     | 
| 
       303 
363 
     | 
    
         
             
                    path = task.files.first['path'].chomp("/tasks/#{task.files.first['name']}")
         
     | 
| 
       304 
     | 
    
         
            -
                     
     | 
| 
       305 
     | 
    
         
            -
             
     | 
| 
       306 
     | 
    
         
            -
             
     | 
| 
       307 
     | 
    
         
            -
             
     | 
| 
       308 
     | 
    
         
            -
             
     | 
| 
       309 
     | 
    
         
            -
             
     | 
| 
      
 364 
     | 
    
         
            +
                    info << colorize(:cyan, "Module\n")
         
     | 
| 
      
 365 
     | 
    
         
            +
                    info << if path.start_with?(Bolt::Config::Modulepath::MODULES_PATH)
         
     | 
| 
      
 366 
     | 
    
         
            +
                              indent(2, 'built-in module')
         
     | 
| 
      
 367 
     | 
    
         
            +
                            else
         
     | 
| 
      
 368 
     | 
    
         
            +
                              indent(2, path)
         
     | 
| 
      
 369 
     | 
    
         
            +
                            end
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
                    @stream.puts info
         
     | 
| 
       310 
372 
     | 
    
         
             
                  end
         
     | 
| 
       311 
373 
     | 
    
         | 
| 
       312 
374 
     | 
    
         
             
                  # @param [Hash] plan A hash representing the plan
         
     | 
| 
       313 
375 
     | 
    
         
             
                  def print_plan_info(plan)
         
     | 
| 
       314 
     | 
    
         
            -
                     
     | 
| 
       315 
     | 
    
         
            -
             
     | 
| 
       316 
     | 
    
         
            -
                     
     | 
| 
       317 
     | 
    
         
            -
             
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
      
 376 
     | 
    
         
            +
                    params = plan['parameters'].sort
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
                    # Add plan name and description
         
     | 
| 
      
 381 
     | 
    
         
            +
                    info << colorize(:cyan, "#{plan['name']}\n")
         
     | 
| 
      
 382 
     | 
    
         
            +
                    info << if plan['description']
         
     | 
| 
      
 383 
     | 
    
         
            +
                              indent(2, plan['description'].chomp)
         
     | 
| 
       319 
384 
     | 
    
         
             
                            else
         
     | 
| 
       320 
     | 
    
         
            -
                               
     | 
| 
      
 385 
     | 
    
         
            +
                              indent(2, 'No description')
         
     | 
| 
       321 
386 
     | 
    
         
             
                            end
         
     | 
| 
      
 387 
     | 
    
         
            +
                    info << "\n\n"
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
                    # Build the usage string
         
     | 
| 
      
 390 
     | 
    
         
            +
                    usage = +''
         
     | 
| 
      
 391 
     | 
    
         
            +
                    usage << if Bolt::Util.powershell?
         
     | 
| 
      
 392 
     | 
    
         
            +
                               "Invoke-BoltPlan -Name #{plan['name']}"
         
     | 
| 
      
 393 
     | 
    
         
            +
                             else
         
     | 
| 
      
 394 
     | 
    
         
            +
                               "bolt plan run #{plan['name']}"
         
     | 
| 
      
 395 
     | 
    
         
            +
                             end
         
     | 
| 
      
 396 
     | 
    
         
            +
                    params.each do |name, data|
         
     | 
| 
      
 397 
     | 
    
         
            +
                      usage << (data.include?('default_value') ? " [#{name}=<value>]" : " #{name}=<value>")
         
     | 
| 
      
 398 
     | 
    
         
            +
                    end
         
     | 
| 
       322 
399 
     | 
    
         | 
| 
       323 
     | 
    
         
            -
                     
     | 
| 
       324 
     | 
    
         
            -
             
     | 
| 
       325 
     | 
    
         
            -
             
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
      
 400 
     | 
    
         
            +
                    # Add usage
         
     | 
| 
      
 401 
     | 
    
         
            +
                    info << colorize(:cyan, "Usage\n")
         
     | 
| 
      
 402 
     | 
    
         
            +
                    info << indent(2, wrap(usage))
         
     | 
| 
      
 403 
     | 
    
         
            +
                    info << "\n"
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
                    # Add parameters, if any
         
     | 
| 
      
 406 
     | 
    
         
            +
                    if params.any?
         
     | 
| 
      
 407 
     | 
    
         
            +
                      info << colorize(:cyan, "Parameters\n")
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
                      params.each do |name, data|
         
     | 
| 
      
 410 
     | 
    
         
            +
                        info << indent(2, "#{colorize(:yellow, name)}  #{colorize(:dim, data['type'])}\n")
         
     | 
| 
      
 411 
     | 
    
         
            +
                        info << indent(4, "#{wrap(data['description']).chomp}\n") if data['description']
         
     | 
| 
      
 412 
     | 
    
         
            +
                        info << indent(4, "Default: #{data['default_value']}\n") unless data['default_value'].nil?
         
     | 
| 
      
 413 
     | 
    
         
            +
                        info << "\n"
         
     | 
| 
      
 414 
     | 
    
         
            +
                      end
         
     | 
| 
       328 
415 
     | 
    
         
             
                    end
         
     | 
| 
       329 
416 
     | 
    
         | 
| 
       330 
     | 
    
         
            -
                     
     | 
| 
       331 
     | 
    
         
            -
                     
     | 
| 
       332 
     | 
    
         
            -
                     
     | 
| 
       333 
     | 
    
         
            -
             
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
      
 417 
     | 
    
         
            +
                    # Add module location
         
     | 
| 
      
 418 
     | 
    
         
            +
                    info << colorize(:cyan, "Module\n")
         
     | 
| 
      
 419 
     | 
    
         
            +
                    info << if plan['module'].start_with?(Bolt::Config::Modulepath::MODULES_PATH)
         
     | 
| 
      
 420 
     | 
    
         
            +
                              indent(2, 'built-in module')
         
     | 
| 
      
 421 
     | 
    
         
            +
                            else
         
     | 
| 
      
 422 
     | 
    
         
            +
                              indent(2, plan['module'])
         
     | 
| 
      
 423 
     | 
    
         
            +
                            end
         
     | 
| 
       336 
424 
     | 
    
         | 
| 
       337 
     | 
    
         
            -
                     
     | 
| 
       338 
     | 
    
         
            -
                    plan_info << if path.start_with?(Bolt::Config::Modulepath::MODULES_PATH)
         
     | 
| 
       339 
     | 
    
         
            -
                                   "built-in module"
         
     | 
| 
       340 
     | 
    
         
            -
                                 else
         
     | 
| 
       341 
     | 
    
         
            -
                                   path
         
     | 
| 
       342 
     | 
    
         
            -
                                 end
         
     | 
| 
       343 
     | 
    
         
            -
                    @stream.puts(plan_info)
         
     | 
| 
      
 425 
     | 
    
         
            +
                    @stream.puts info
         
     | 
| 
       344 
426 
     | 
    
         
             
                  end
         
     | 
| 
       345 
427 
     | 
    
         | 
| 
       346 
428 
     | 
    
         
             
                  def print_plans(plans, modulepath)
         
     | 
| 
         @@ -401,42 +483,115 @@ module Bolt 
     | 
|
| 
       401 
483 
     | 
    
         
             
                    end
         
     | 
| 
       402 
484 
     | 
    
         
             
                  end
         
     | 
| 
       403 
485 
     | 
    
         | 
| 
       404 
     | 
    
         
            -
                  def print_targets(target_list,  
     | 
| 
      
 486 
     | 
    
         
            +
                  def print_targets(target_list, inventory_source, default_inventory, target_flag)
         
     | 
| 
       405 
487 
     | 
    
         
             
                    adhoc = colorize(:yellow, "(Not found in inventory file)")
         
     | 
| 
       406 
488 
     | 
    
         | 
| 
       407 
489 
     | 
    
         
             
                    targets  = []
         
     | 
| 
       408 
490 
     | 
    
         
             
                    targets += target_list[:inventory].map { |target| [target.name, nil] }
         
     | 
| 
       409 
491 
     | 
    
         
             
                    targets += target_list[:adhoc].map { |target| [target.name, adhoc] }
         
     | 
| 
       410 
492 
     | 
    
         | 
| 
       411 
     | 
    
         
            -
                     
     | 
| 
       412 
     | 
    
         
            -
                      @stream.puts format_table(targets, 0, 2)
         
     | 
| 
       413 
     | 
    
         
            -
                      @stream.puts
         
     | 
| 
       414 
     | 
    
         
            -
                    end
         
     | 
| 
      
 493 
     | 
    
         
            +
                    info = +''
         
     | 
| 
       415 
494 
     | 
    
         | 
| 
       416 
     | 
    
         
            -
                     
     | 
| 
       417 
     | 
    
         
            -
                     
     | 
| 
       418 
     | 
    
         
            -
             
     | 
| 
      
 495 
     | 
    
         
            +
                    # Add target list
         
     | 
| 
      
 496 
     | 
    
         
            +
                    info << colorize(:cyan, "Targets\n")
         
     | 
| 
      
 497 
     | 
    
         
            +
                    info << if targets.any?
         
     | 
| 
      
 498 
     | 
    
         
            +
                              format_table(targets, 2, 2).to_s
         
     | 
| 
      
 499 
     | 
    
         
            +
                            else
         
     | 
| 
      
 500 
     | 
    
         
            +
                              indent(2, 'No targets')
         
     | 
| 
      
 501 
     | 
    
         
            +
                            end
         
     | 
| 
      
 502 
     | 
    
         
            +
                    info << "\n\n"
         
     | 
| 
      
 503 
     | 
    
         
            +
             
     | 
| 
      
 504 
     | 
    
         
            +
                    info << format_inventory_source(inventory_source, default_inventory)
         
     | 
| 
      
 505 
     | 
    
         
            +
                    info << format_target_summary(target_list[:inventory].count, target_list[:adhoc].count, target_flag, false)
         
     | 
| 
      
 506 
     | 
    
         
            +
             
     | 
| 
      
 507 
     | 
    
         
            +
                    @stream.puts info
         
     | 
| 
      
 508 
     | 
    
         
            +
                  end
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                  def print_target_info(target_list, inventory_source, default_inventory, target_flag)
         
     | 
| 
      
 511 
     | 
    
         
            +
                    adhoc_targets     = target_list[:adhoc].map(&:name).to_set
         
     | 
| 
      
 512 
     | 
    
         
            +
                    inventory_targets = target_list[:inventory].map(&:name).to_set
         
     | 
| 
      
 513 
     | 
    
         
            +
                    targets           = target_list.values.flatten.sort_by(&:name)
         
     | 
| 
      
 514 
     | 
    
         
            +
             
     | 
| 
      
 515 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 516 
     | 
    
         
            +
             
     | 
| 
      
 517 
     | 
    
         
            +
                    if targets.any?
         
     | 
| 
      
 518 
     | 
    
         
            +
                      adhoc = colorize(:yellow, " (Not found in inventory file)")
         
     | 
| 
      
 519 
     | 
    
         
            +
             
     | 
| 
      
 520 
     | 
    
         
            +
                      targets.each do |target|
         
     | 
| 
      
 521 
     | 
    
         
            +
                        info << colorize(:cyan, target.name)
         
     | 
| 
      
 522 
     | 
    
         
            +
                        info << adhoc if adhoc_targets.include?(target.name)
         
     | 
| 
      
 523 
     | 
    
         
            +
                        info << "\n"
         
     | 
| 
      
 524 
     | 
    
         
            +
                        info << indent(2, target.detail.to_yaml.lines.drop(1).join)
         
     | 
| 
      
 525 
     | 
    
         
            +
                        info << "\n"
         
     | 
| 
      
 526 
     | 
    
         
            +
                      end
         
     | 
| 
       419 
527 
     | 
    
         
             
                    else
         
     | 
| 
       420 
     | 
    
         
            -
                       
     | 
| 
      
 528 
     | 
    
         
            +
                      info << colorize(:cyan, "Targets\n")
         
     | 
| 
      
 529 
     | 
    
         
            +
                      info << indent(2, "No targets\n\n")
         
     | 
| 
       421 
530 
     | 
    
         
             
                    end
         
     | 
| 
       422 
531 
     | 
    
         | 
| 
       423 
     | 
    
         
            -
                     
     | 
| 
       424 
     | 
    
         
            -
                     
     | 
| 
       425 
     | 
    
         
            -
             
     | 
| 
      
 532 
     | 
    
         
            +
                    info << format_inventory_source(inventory_source, default_inventory)
         
     | 
| 
      
 533 
     | 
    
         
            +
                    info << format_target_summary(inventory_targets.count, adhoc_targets.count, target_flag, true)
         
     | 
| 
      
 534 
     | 
    
         
            +
             
     | 
| 
      
 535 
     | 
    
         
            +
                    @stream.puts info
         
     | 
| 
       426 
536 
     | 
    
         
             
                  end
         
     | 
| 
       427 
537 
     | 
    
         | 
| 
       428 
     | 
    
         
            -
                  def  
     | 
| 
       429 
     | 
    
         
            -
                     
     | 
| 
       430 
     | 
    
         
            -
             
     | 
| 
       431 
     | 
    
         
            -
                     
     | 
| 
       432 
     | 
    
         
            -
                     
     | 
| 
       433 
     | 
    
         
            -
                     
     | 
| 
      
 538 
     | 
    
         
            +
                  private def format_inventory_source(inventory_source, default_inventory)
         
     | 
| 
      
 539 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 540 
     | 
    
         
            +
             
     | 
| 
      
 541 
     | 
    
         
            +
                    # Add inventory file source
         
     | 
| 
      
 542 
     | 
    
         
            +
                    info << colorize(:cyan, "Inventory source\n")
         
     | 
| 
      
 543 
     | 
    
         
            +
                    info << if inventory_source
         
     | 
| 
      
 544 
     | 
    
         
            +
                              indent(2, "#{inventory_source}\n")
         
     | 
| 
      
 545 
     | 
    
         
            +
                            else
         
     | 
| 
      
 546 
     | 
    
         
            +
                              indent(2, wrap("Tried to load inventory from #{default_inventory}, but the file does not exist\n"))
         
     | 
| 
      
 547 
     | 
    
         
            +
                            end
         
     | 
| 
      
 548 
     | 
    
         
            +
                    info << "\n"
         
     | 
| 
       434 
549 
     | 
    
         
             
                  end
         
     | 
| 
       435 
550 
     | 
    
         | 
| 
       436 
     | 
    
         
            -
                  def  
     | 
| 
       437 
     | 
    
         
            -
                     
     | 
| 
       438 
     | 
    
         
            -
             
     | 
| 
       439 
     | 
    
         
            -
                     
     | 
| 
      
 551 
     | 
    
         
            +
                  private def format_target_summary(inventory_count, adhoc_count, target_flag, detail_flag)
         
     | 
| 
      
 552 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 553 
     | 
    
         
            +
             
     | 
| 
      
 554 
     | 
    
         
            +
                    # Add target count summary
         
     | 
| 
      
 555 
     | 
    
         
            +
                    count = "#{inventory_count + adhoc_count} total, "\
         
     | 
| 
      
 556 
     | 
    
         
            +
                            "#{inventory_count} from inventory, "\
         
     | 
| 
      
 557 
     | 
    
         
            +
                            "#{adhoc_count} adhoc"
         
     | 
| 
      
 558 
     | 
    
         
            +
                    info << colorize(:cyan, "Target count\n")
         
     | 
| 
      
 559 
     | 
    
         
            +
                    info << indent(2, count)
         
     | 
| 
      
 560 
     | 
    
         
            +
             
     | 
| 
      
 561 
     | 
    
         
            +
                    # Add filtering information
         
     | 
| 
      
 562 
     | 
    
         
            +
                    unless target_flag && detail_flag
         
     | 
| 
      
 563 
     | 
    
         
            +
                      info << colorize(:cyan, "\n\nAdditional information\n")
         
     | 
| 
      
 564 
     | 
    
         
            +
             
     | 
| 
      
 565 
     | 
    
         
            +
                      unless target_flag
         
     | 
| 
      
 566 
     | 
    
         
            +
                        opt = Bolt::Util.windows? ? "'-Targets', '-Query', or '-Rerun'" : "'--targets', '--query', or '--rerun'"
         
     | 
| 
      
 567 
     | 
    
         
            +
                        info << indent(2, "Use the #{opt} option to view specific targets\n")
         
     | 
| 
      
 568 
     | 
    
         
            +
                      end
         
     | 
| 
      
 569 
     | 
    
         
            +
             
     | 
| 
      
 570 
     | 
    
         
            +
                      unless detail_flag
         
     | 
| 
      
 571 
     | 
    
         
            +
                        opt = Bolt::Util.windows? ? '-Detail' : '--detail'
         
     | 
| 
      
 572 
     | 
    
         
            +
                        info << indent(2, "Use the '#{opt}' option to view target configuration and data")
         
     | 
| 
      
 573 
     | 
    
         
            +
                      end
         
     | 
| 
      
 574 
     | 
    
         
            +
                    end
         
     | 
| 
      
 575 
     | 
    
         
            +
             
     | 
| 
      
 576 
     | 
    
         
            +
                    info
         
     | 
| 
      
 577 
     | 
    
         
            +
                  end
         
     | 
| 
      
 578 
     | 
    
         
            +
             
     | 
| 
      
 579 
     | 
    
         
            +
                  def print_groups(groups, inventory_source, default_inventory)
         
     | 
| 
      
 580 
     | 
    
         
            +
                    info = +''
         
     | 
| 
      
 581 
     | 
    
         
            +
             
     | 
| 
      
 582 
     | 
    
         
            +
                    # Add group list
         
     | 
| 
      
 583 
     | 
    
         
            +
                    info << colorize(:cyan, "Groups\n")
         
     | 
| 
      
 584 
     | 
    
         
            +
                    info << indent(2, groups.join("\n"))
         
     | 
| 
      
 585 
     | 
    
         
            +
                    info << "\n\n"
         
     | 
| 
      
 586 
     | 
    
         
            +
             
     | 
| 
      
 587 
     | 
    
         
            +
                    # Add inventory file source
         
     | 
| 
      
 588 
     | 
    
         
            +
                    info << format_inventory_source(inventory_source, default_inventory)
         
     | 
| 
      
 589 
     | 
    
         
            +
             
     | 
| 
      
 590 
     | 
    
         
            +
                    # Add group count summary
         
     | 
| 
      
 591 
     | 
    
         
            +
                    info << colorize(:cyan, "Group count\n")
         
     | 
| 
      
 592 
     | 
    
         
            +
                    info << indent(2, "#{groups.count} total")
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
      
 594 
     | 
    
         
            +
                    @stream.puts info
         
     | 
| 
       440 
595 
     | 
    
         
             
                  end
         
     | 
| 
       441 
596 
     | 
    
         | 
| 
       442 
597 
     | 
    
         
             
                  # @param [Bolt::ResultSet] apply_result A ResultSet object representing the result of a `bolt apply`
         
     | 
| 
         @@ -452,6 +607,10 @@ module Bolt 
     | 
|
| 
       452 
607 
     | 
    
         
             
                      @stream.puts("Plan completed successfully with no result")
         
     | 
| 
       453 
608 
     | 
    
         
             
                    when Bolt::ApplyFailure, Bolt::RunFailure
         
     | 
| 
       454 
609 
     | 
    
         
             
                      print_result_set(value.result_set)
         
     | 
| 
      
 610 
     | 
    
         
            +
                    when Bolt::ContainerResult
         
     | 
| 
      
 611 
     | 
    
         
            +
                      print_container_result(value)
         
     | 
| 
      
 612 
     | 
    
         
            +
                    when Bolt::ContainerFailure
         
     | 
| 
      
 613 
     | 
    
         
            +
                      print_container_result(value.result)
         
     | 
| 
       455 
614 
     | 
    
         
             
                    when Bolt::ResultSet
         
     | 
| 
       456 
615 
     | 
    
         
             
                      print_result_set(value)
         
     | 
| 
       457 
616 
     | 
    
         
             
                    else
         
     |